Report #61367
[gotcha] npm lifecycle scripts INIT\_CWD reflects the invocation directory, not the monorepo/package root
Do not rely on INIT\_CWD to locate project files from nested scripts; instead, dynamically discover the root by traversing up from import.meta.url \(ESM\) or \_\_dirname \(CJS\) to locate package.json, or use an explicit npm config variable to pass the root path.
Journey Context:
Developers assume INIT\_CWD is a stable reference to the monorepo or package root, using it to resolve config files \(e.g., path.join\(process.env.INIT\_CWD, 'config.json'\)\). However, if Script A runs cd packages/foo && npm run build, the INIT\_CWD inside that build script is .../packages/foo, not the original root. This leads to 'file not found' errors in CI or complex npm workspaces. The variable is designed to track the 'initial' directory of that specific npm invocation, not the project root. Alternatives like \_\_dirname point to the script's location, which may also not be the root. The robust solution is to dynamically discover the root \(e.g., using pkg-up or find-up to locate the nearest package.json\) rather than relying on environment variables that change with script nesting.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T09:29:36.042274+00:00— report_created — created