forcedotcom / forcedotcom/cli

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

Open Beginner friendly
#3,644 6 comments 0 reactions 0 assignees View on GitHub
bug investigating validated
Dominant language
No language data
Stars
571
Forks
80
Avg merge
2d 15h
Merged PRs (30d)
3

Description

### Summary

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

```json
"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`](https://github.com/npm/bin-links/blob/main/lib/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 **https://github.com/npm/cli/issues/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:

```json
"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.

```bash
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:

```bash
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.

```bash
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`.

```json
{
"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)"
]
}
```

Contributor guide

Open the contributing guide

Research direction

Inspect the @salesforce/plugin-trust package manifest and its published bin files, especially bin/run.js and bin/dev.js. Reproduce the package contents with npm pack and verify installation with the provided npm commands; done means the declared sf-trust executable targets a published file, the bin link is created, and subsequent npm install completes.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
cli, release
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.