AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

Next.Config.Ts Relative Imports Resolve Against Process.Cwd() Instead Of The Config File'S Directory

When Next.js is invoked from a directory other than the project root (e.g., `node app/node_modules/next/dist/bin/next build app`), relative imports in `next.config.ts` are resolved against `process.cwd()` instead of the config file's directory. This causes builds to fail with `Cannot find module` or silently load a wrong file if a similarly named file exists in the cwd. The issue affects the default SWC transpilation path and has been present since Next.js 15.0.0.

highConfidence 95%Next.jsAffected V15.0.0Affected V15.5.26Affected V16.4.0-Canary.63

Origin Analysis

In `packages/next/src/build/next-config-ts/require-hook.ts`, `requireFromString` creates a Node.js `Module` instance with `new Module(filename, module.parent!)` but only sets `m.paths`, not `m.filename`. Without `m.filename`, Node's `Module._resolveLookupPaths` treats the module like a REPL and resolves relative requests against `'.'` (i.e., `process.cwd()`). Thus `./src/headers` in `next.config.ts` is looked up from wherever the command was run, not adjacent to the config file.
1. Clone https://github.com/dxdc/next-config-ts-cwd-repro and install dependencies inside `app/`. 2. Run `(cd app && npx next build)` — build succeeds. 3. Run `node app/node_modules/next/dist/bin/next build app` from the parent directory — build fails with `Cannot find module './src/headers'`. 4. Create `src/headers.ts` in the parent directory with a different header value and run the same command again — build now succeeds but uses the wrong file (value `WRONG-cwd` instead of `app`).

Fixing Code Block

Edge Case Audit

This change may break code that unintentionally relied on the buggy cwd-based resolution (e.g., configs that expected to load files from the invoking directory). If any deployment depends on the previous behavior, roll back by removing the `m.filename = filename` line. The fix only affects the default SWC transpilation path; the experimental `--experimental-next-config-strip-types` path uses native `import()` and is already correct. Test in monorepo and CI environments where the working directory differs from the project directory. Also be aware that setting `m.filename` changes the module's identity in Node's `require.cache`, which could affect hot reload or module duplication in edge cases; using absolute paths in `next.config.ts` is a safer interim workaround.

Ecosystem Topology