Summary
ts-scan scan fails on npm workspace monorepos with the error:
✘ An error occured while scanning Node dependencies...
✘ 'version'
Root Cause
npm workspaces store linked packages in package-lock.json without a version field:
"node_modules/@ts-psirt/shared": {
"resolved": "packages/shared",
"link": true
}
Regular dependencies have a version field, but workspace-linked packages only have resolved and link. ts-scan appears to access .version unconditionally on all node_modules/* entries, causing a KeyError on workspace links.
Reproduction
-
Create an npm workspace monorepo:
package.json (with "workspaces": ["packages/*"])
package-lock.json (generated by npm install)
packages/
backend/package.json (depends on "@my/shared": "*")
shared/package.json
-
Run: ts-scan scan --output sbom.json .
-
Result: scan fails with ✘ 'version'
Expected Behavior
ts-scan should skip or gracefully handle link: true entries in the lockfile. These are local workspace references, not external dependencies — they don't belong in the SBOM anyway.
Environment
- ts-scan: latest (pip install ts-scan)
- npm: 10.x
- Node.js: 22.x / 24.x
- OS: macOS / Ubuntu (GitHub Actions)
Summary
ts-scan scanfails on npm workspace monorepos with the error:Root Cause
npm workspaces store linked packages in
package-lock.jsonwithout aversionfield:Regular dependencies have a
versionfield, but workspace-linked packages only haveresolvedandlink. ts-scan appears to access.versionunconditionally on allnode_modules/*entries, causing a KeyError on workspace links.Reproduction
Create an npm workspace monorepo:
Run:
ts-scan scan --output sbom.json .Result: scan fails with
✘ 'version'Expected Behavior
ts-scan should skip or gracefully handle
link: trueentries in the lockfile. These are local workspace references, not external dependencies — they don't belong in the SBOM anyway.Environment