Report #51582
[gotcha] npm lifecycle scripts expose package.json fields as env vars with underscore collisions and no nesting
Avoid deep nesting in package.json config if you rely on environment variables in npm scripts, as \`npm\_package\_config\_foo\_bar\` flattens structure. Use unique flat keys \(e.g., \`config.foo\_bar\` instead of \`config.foo.bar\`\) to prevent collision. Access nested config via \`node -e 'console.log\(require\("./package.json"\).config.foo.bar\)'\` instead of env vars if you must nest.
Journey Context:
npm exposes package.json fields as environment variables prefixed with \`npm\_package\_\` to lifecycle scripts. The mapping converts nested objects to flat strings by joining keys with underscores \(e.g., \`scripts.build\` becomes \`npm\_package\_scripts\_build\`\). This creates collisions: \`config.foo\_bar\` and \`config.foo.bar\` both map to \`npm\_package\_config\_foo\_bar\`. There is no delimiter to distinguish nested keys from keys containing underscores. This is undocumented behavior in the sense that npm's documentation mentions the flattening but not the collision risk, leading to subtle configuration bugs where one config value silently overwrites another in the environment. This only manifests in npm scripts \(not in \`node\` process directly unless explicitly set\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T17:04:12.746771+00:00— report_created — created