Skip to content

darwin binary fails on non-Nix Macs: dyld can't load libiconv.2.dylib from hardcoded /nix/store path (v20.0.10) #1251

Description

@chufnagel

[email protected] crashes on launch on any Mac without Nix. The published darwin
binary links libiconv from a /nix/store/... path that only exists on the build machine:

dyld: Library not loaded: /nix/store/xvmhkpvfvmy4sfdkqwg9inq3qkpnx81b-libiconv-109.100.2/lib/libiconv.2.dylib
  Referenced from: .../@ccusage/ccusage-darwin-arm64/bin/ccusage

It's a regression in 20.0.10 only. Checking the published binaries with otool -L:

  • 20.0.0–20.0.9: both darwin-arm64 and darwin-x64 link /usr/lib/libiconv.2.dylib (fine)
  • 20.0.10: both link a /nix/store/...libiconv.2.dylib path (broken)

Workaround: pin to 20.0.9 (npx [email protected]); its binary links the system libiconv per otool.

Tested on Apple Silicon, macOS (Darwin 25.5.0), no Nix installed.

Activity

  1. github-actions commented on Jun 10, 2026

    @github-actions
    Contributor

    This issue was auto-closed. Issues from new contributors are auto-closed by default.

    Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply.

    Keep the issue short, concrete, and written in your own voice.

    If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

    See CONTRIBUTING.md.

  2. chaserx commented on Jun 10, 2026

    @chaserx

    Thank you for this issue. I can confirm that pinning to 19.0.2 works on macOS 26.5.1 (Apple Silicon; w/o nix installed).

  3. SeanLF commented on Jun 10, 2026

    @SeanLF

    Confirmed on Darwin 27.0.0 (Apple Silicon, no Nix), v20.0.10. Same load command as reported, and the macOS 26 confirmation above matches: this fails on any Mac without Nix, regardless of OS version.

    Root cause is in the Nix build: package.nix adds nixpkgs libiconv to the darwin buildInputs, and release.yaml publishes the nix build .#ccusage output to npm as-is. Nothing in Cargo.lock references iconv, so the linkage comes purely from the build environment. The release workflow verifies the Linux binary is static but has no equivalent guard for darwin, which is how the store path shipped unnoticed.

    I verified the fix at the artifact level: rewriting the load command in the published 20.0.10 binary and re-signing makes it run correctly on a Mac without Nix:

    $ install_name_tool -change /nix/store/xvmhkpvfvmy4sfdkqwg9inq3qkpnx81b-libiconv-109.100.2/lib/libiconv.2.dylib /usr/lib/libiconv.2.dylib ccusage
    $ codesign -f -s - ccusage
    $ ./ccusage --version
    ccusage 20.0.10

    macOS ships /usr/lib/libiconv.2.dylib with the same compatibility version (7.0.0), so the swap is safe.

    Proposed build fix, the same rewrite at build time plus a guard so it cannot regress:

    --- a/package.nix
    +++ b/package.nix
    @@ craneLib.buildPackage (
       commonArgs
       // {
         inherit cargoArtifacts;
    +    # The npm-published darwin binary must run on machines without Nix:
    +    # relink libiconv to the system copy and fail if any store path remains.
    +    postFixup = lib.optionalString stdenv.isDarwin ''
    +      install_name_tool -change ${lib.getLib libiconv}/lib/libiconv.2.dylib /usr/lib/libiconv.2.dylib "$out/bin/ccusage"
    +      if otool -L "$out/bin/ccusage" | grep -q '/nix/store/'; then
    +        echo "error: ccusage still links against Nix store libraries" >&2
    +        otool -L "$out/bin/ccusage" >&2
    +        exit 1
    +      fi
    +    '';

    And in release.yaml, mirroring the existing "Verify Linux binary is static" step:

    - name: Verify macOS binary has no Nix store references
      if: matrix.platform == 'darwin'
      shell: bash
      run: |
        otool -L "${{ matrix.binary }}"
        ! otool -L "${{ matrix.binary }}" | grep '/nix/store/'

    One caveat I could not verify locally (no Nix on this machine): on aarch64-darwin the binary needs re-signing after modification. Recent nixpkgs wraps install_name_tool to re-sign automatically; if that does not hold for the pinned nixpkgs here, the postFixup needs an explicit ad-hoc codesign or autoSignDarwinBinariesHook.

    Workaround until a fixed release: npx [email protected] (last release before the compiled binaries).

    Happy to open a PR with the above if approved.

  4. added a commit that references this issue on Jun 10, 2026
    b4e625e
  5. ryoppippi commented on Jun 10, 2026

    @ryoppippi
    Member

    Thank you guys. this is the issue we are migrating into a new ci env.
    so sorry!

    will fix it soon!!!

  6. added a commit that references this issue on Jun 10, 2026
    b47a31a
  7. ryoppippi commented on Jun 10, 2026

    @ryoppippi
    Member

    guys i hit the publish button. let's see

  8. SeanLF commented on Jun 11, 2026

    @SeanLF

    Confirmed fixed on my end. Thanks Ryo!

  9. ryoppippi commented on Aug 31, 2026

    @ryoppippi
    Member

    Historical audit: this discussion was auto-closed by the legacy contributor gate. That closure did not assess technical importance.

    Audit result: resolved. A later merged change or the current main implementation covers this request. This item is kept for history and does not need to be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage:resolvedResolved by a later change or current implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions