Skip to content

@salesforce/plugin-trust bin points to unpublished bin/dev, breaking npm install #3644

Description

@amurashincertinia

Summary

@salesforce/plugin-trust declares a bin entry that points at a file it does not publish:

"bin": { "sf-trust": "bin/dev" }

The published tarball contains bin/dev.js, bin/dev.cmd, bin/run.js and bin/run.cmd — there is no extensionless bin/dev. Confirmed in @salesforce/plugin-trust@4.0.9 (bundled with @salesforce/cli@2.149.9) and @salesforce/plugin-trust@4.0.11 (bundled with the current latest @salesforce/cli@2.150.6).

Because the bin target doesn't resolve, npm's bin-links silently skips it (link-gently.js, "if the script or manpage isn't there, just ignore it"), so node_modules/@salesforce/cli/node_modules/.bin/sf-trust is never created — not even by a clean install.

On its own that would be a harmless cosmetic bug. In practice it permanently breaks npm install for every project that depends on @salesforce/cli, because it trips a latent npm/arborist bug:

  • arborist's getAction classifies a node as CHANGE when any of its declared bins is missing from disk, so plugin-trust is CHANGE on every install forever, despite matching version and integrity.
  • That CHANGE node lives inside @salesforce/cli's npm-shrinkwrap.json subtree, which arborist only diffs after it has already decided which directories to move aside for rollback. The node therefore has no rollback entry, and npm install crashes with ERR_INVALID_ARG_TYPE: The "from" argument must be of type string. Received undefined.
  • The crash happens before the step that creates bin links, so the missing link can never get created and every subsequent install fails identically.

I've filed the npm-side analysis at npm/cli#4907 (an open issue since 2022 that nobody had root-caused). npm should certainly fix its end — but @salesforce/cli is currently the trigger that makes it fire for everyone, and the fix on this side is a one-line change.

Suggested fix: point the bin at the published production entry point rather than the ts-node development one:

"bin": { "sf-trust": "bin/run.js" }

bin/dev.js has the shebang #!/usr/bin/env -S node --loader ts-node/esm and is not usable from a published package anyway (ts-node isn't a runtime dependency). bin/run.js is the correct entry. Alternatively, if sf-trust isn't meant to be a user-facing executable at all, drop the bin field.

Steps To Reproduce

A dedicated repo isn't needed — this reproduces from a two-line package.json with no Salesforce project or org involved, since the failure happens at npm install time. Verified on the latest @salesforce/cli@2.150.6 against the public npm registry.

mkdir sf-bin-repro && cd sf-bin-repro
cat > package.json <<'EOF'
{ "name": "sf-bin-repro", "version": "1.0.0", "private": true,
  "devDependencies": { "@salesforce/cli": "2.150.6", "lint-staged": "17.4.1" } }
EOF

# 1. clean install — succeeds
npm install

# 2. the declared bin was never linked
ls -la node_modules/@salesforce/cli/node_modules/.bin/sf-trust

# 3. now update any unrelated dependency, with node_modules still in place
npm i -D lint-staged@17.5.0

To see the packaging bug in isolation, without any npm interaction:

npm pack @salesforce/plugin-trust@4.0.11
tar tzf salesforce-plugin-trust-4.0.11.tgz | grep '^package/bin/'
# package/bin/dev.cmd
# package/bin/dev.js
# package/bin/run.cmd
# package/bin/run.js          <-- no extensionless "bin/dev"

npm view @salesforce/plugin-trust@4.0.11 bin
# { 'sf-trust': 'bin/dev' }

Expected result

  • node_modules/@salesforce/cli/node_modules/.bin/sf-trust exists after installation, pointing at a file that is actually published.
  • Step 3 completes normally.

Actual result

Step 2:

ls: node_modules/@salesforce/cli/node_modules/.bin/sf-trust: No such file or directory

Step 3:

npm error code ERR_INVALID_ARG_TYPE
npm error The "from" argument must be of type string. Received undefined

Every subsequent npm install in that project fails the same way until node_modules is deleted entirely — and it starts failing again as soon as the tree is reinstalled, because the bin link is still never created.

A retry after the first crash produces a second, different failure, because npm's failed rollback leaves its staging directories behind:

npm error code ENOTEMPTY
npm error syscall rename
npm error path .../node_modules/lint-staged
npm error dest .../node_modules/.lint-staged-gfX1MQHW

Additional information

Verified that this is the sole cause of the install failure: creating the missing link by hand makes the node compare equal and the install succeed immediately, with no other change.

P=node_modules/@salesforce/cli/node_modules/@salesforce/plugin-trust
printf '#!/usr/bin/env node\n' > "$P/bin/dev" && chmod +x "$P/bin/dev"
ln -sfn ../@salesforce/plugin-trust/bin/dev \
        node_modules/@salesforce/cli/node_modules/.bin/sf-trust

npm i -D lint-staged
# added 1 package, changed 163 packages, and audited 2563 packages in 10s

Measured with arborist's own diffing API before and after that change:

before: never-retired orphan nodes: 91,  orphans that trigger the crash: 1  (@salesforce/plugin-trust)
after : never-retired orphan nodes: 90,  orphans that trigger the crash: 0

Note on the issue template: sf doctor isn't applicable here — the CLI itself runs fine, and the failure is in npm install of a project that depends on @salesforce/cli, before any sf command is involved.

System Information

Shell: zsh on macOS (Darwin 25.6.0, arm64), Node v22.22.3, npm 10.9.8.

The project below pins @salesforce/cli@2.149.9, but as noted above the packaging bug and the resulting install failure are both confirmed on the current latest, 2.150.6.

{
  "architecture": "darwin-arm64",
  "cliVersion": "@salesforce/cli/2.149.9",
  "nodeVersion": "node-v22.22.3",
  "osVersion": "Darwin 25.6.0",
  "rootPath": "/Users/…/node_modules/@salesforce/cli",
  "shell": "zsh",
  "pluginVersions": [
    "@oclif/plugin-autocomplete 3.2.56 (core)",
    "@oclif/plugin-commands 4.1.63 (core)",
    "@oclif/plugin-help 6.2.58 (core)",
    "@oclif/plugin-not-found 3.2.93 (core)",
    "@oclif/plugin-plugins 5.4.87 (core)",
    "@oclif/plugin-search 1.2.54 (core)",
    "@oclif/plugin-update 4.7.59 (core)",
    "@oclif/plugin-version 2.2.57 (core)",
    "@oclif/plugin-warn-if-update-available 3.1.73 (core)",
    "@oclif/plugin-which 3.2.61 (core)",
    "@salesforce/cli 2.149.9 (core)",
    "agent 2.0.3 (core)",
    "apex 4.1.0 (core)",
    "api 2.0.9 (core)",
    "auth 5.0.6 (core)",
    "code-analyzer 5.0.0 (user) published 495 days ago (Tue Apr 29 2025) (latest is 5.16.0)",
    "data 5.1.5 (core)",
    "deploy-retrieve 4.1.2 (core)",
    "info 4.0.9 (core)",
    "lightning-dev 3.5.1 (user) published 375 days ago (Wed Aug 27 2025) (latest is 6.2.18)",
    "limits 4.0.3 (core)",
    "marketplace 2.0.5 (core)",
    "org 6.0.9 (core)",
    "packaging 3.0.5 (core)",
    "schema 4.0.5 (core)",
    "settings 3.0.5 (core)",
    "sobject 2.0.5 (core)",
    "telemetry 4.0.5 (core)",
    "templates 57.0.9 (core)",
    "trust 4.0.9 (core)",
    "ui-bundle-dev 1.2.2 (user) published 159 days ago (Tue Mar 31 2026) (latest is 1.2.4)",
    "user 5.0.1 (core)"
  ]
}

Activity

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

    bugIssue or pull request that identifies or fixes a buginvestigatingWe're actively investigating this issuevalidatedVersion information for this issue has been validated

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions