NestJS Prisma 7: Fix Module Not Found Error After Upgrade
Resolve NestJS Prisma 7 upgrade error: ERR_MODULE_NOT_FOUND for app.module after successful build. Configure tsconfig.json to CommonJS, handle Prisma client generation, and fix module resolution for runtime compatibility.
NestJS Prisma 7 upgrade error: [ERR_MODULE_NOT_FOUND] Cannot find module ‘app.module’ after successful build
I’m using NestJS v11.1.6 for the backend with Prisma and NextJS for the frontend. After upgrading from Prisma v6 to v7 following the migration guide, the project builds successfully, but running it locally fails with this error:
[ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/Projects/project-example/backend/dist/src/app.module' imported from /Users/Projects/project-example/backend/dist/src/main.js
I’ve updated prisma.config.ts:
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: env("DATABASE_URL"),
},
});
And tsconfig.json:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "node",
"declaration": false,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "ES2023",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"skipLibCheck": true,
"strict": true,
"esModuleInterop": true
}
}
How can I resolve this module resolution issue with Prisma 7 and NestJS? What configuration changes or steps are needed for compatibility?
The error means Node can’t resolve the module layout produced by your TypeScript build after the Prisma 7 upgrade: Prisma 7 ships a CommonJS Prisma Client while your tsconfig.json is producing ESM output (module: “ESNext”), so the compiled imports don’t match at runtime. The simplest, lowest‑friction fix is to compile your NestJS backend to CommonJS (set "module": "CommonJS"), ensure prisma.config.ts is included in the compiled output, run prisma generate, rebuild, and run the built files; full ESM migration is possible but requires extra changes (package.json "type", file extensions, or runtime interop).
Contents
- tsconfig.json Configuration for NestJS Prisma 7
- CommonJS vs ESM with Prisma 7
- Prisma Client generation and prisma.config.ts
- Debug checklist and quick fixes
- Sources
- Conclusion
tsconfig.json Configuration for NestJS Prisma 7
Why this error happens (short): TypeScript compiled your source to ESM-style modules (module: “ESNext”), producing dist/.../*.js that use ESM import syntax and/or extensionless import specifiers. Prisma 7’s generated client is CommonJS‑oriented, so when Node tries to resolve an import like ./app.module from a compiled main.js it fails because the runtime module format and file specifiers don’t line up.
Quick recommended change (most projects switch back to CommonJS after upgrading Prisma 7):
- Edit
tsconfig.jsonto emit CommonJS modules and ensure Prisma config is included in the build:
{
"compilerOptions": {
"module": "CommonJS",
"moduleResolution": "node",
"target": "ES2023",
"outDir": "./dist",
"rootDir": "src",
"declaration": false,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"skipLibCheck": true,
"strict": true,
"esModuleInterop": true
},
"include": ["src/**/*", "prisma.config.ts"]
}
Notes and rationale:
module: "CommonJS"producesrequire()output that Node resolves in the usual way and avoids extension/specifier mismatches. This is the lowest-effort compatibility fix.rootDir: "src"keepsdist/structure asdist/instead ofdist/src/(optional, but handy).- Adding
prisma.config.tstoincludemakes sure the Prisma config is compiled intodist(see the next section). - After changing tsconfig, rebuild:
rm -rf dist && npx tsc -p tsconfig.json.
Typical scripts:
"scripts": {
"build": "tsc -p tsconfig.json",
"start:prod": "node dist/src/main.js"
}
If your package.json contains "type": "module", remove it (or ensure you use a full ESM migration) — otherwise Node will treat .js as ESM which will reintroduce format mismatch.
For more context see the community report on the same symptom: the Stack Overflow thread describing Prisma7 and NestJS module conflicts explains this mismatch and the fix to match TypeScript module output to Node runtime: https://stackoverflow.com/questions/79860717/prisma7-and-nestjs-module-conflicts
CommonJS vs ESM with Prisma 7
The tradeoff: use CommonJS (fast path) or fully migrate to ESM (more work).
Option A — Keep everything CommonJS (recommended now)
- Set
"module": "CommonJS"intsconfig.json. - Ensure
package.jsondoes not set"type": "module". - Rebuild and run the built JS with
node dist/.... - This avoids needing to change source imports or deal with Prisma’s CommonJS client.
Option B — Full ESM migration (only if you need ESM)
- Set
package.json"type": "module". - Use TypeScript settings designed for Node ESM:
"module": "NodeNext"and"moduleResolution": "NodeNext". - Update imports in your
.tsfiles to include.jsextensions for relative imports (for example:import { AppModule } from './app.module.js') so the emitted ESM code resolves in Node. - You’ll still need to handle Prisma’s CommonJS build. Two common solutions:
- Import Prisma Client using
createRequireinside an ESM module:
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { PrismaClient } = require("./node_modules/.prisma/client");
- Or dynamically
await import()a transpiled CommonJS wrapper that exposes PrismaClient. - Expect more friction: many tooling and libs may need updates; tests, CI, and deploy must support Node ESM.
If you want to experiment with ESM, read the GitHub issue where a NestJS app failed to find a generated Prisma client path and the discussion about custom outputs and Node resolution: https://github.com/prisma/prisma/issues/21066
Prisma Client generation and prisma.config.ts
A few Prisma‑specific gotchas after v7:
- Keep
prisma.config.ts(or its compiledprisma.config.js) available at runtime. The v7 config system expects the config file to be discoverable; if you moved/removed it the CLI or runtime may fail. The safest approach: keepprisma.config.tsin the project root and add it totsconfig.jsonincludesotscemitsdist/prisma.config.js. - Always run
npx prisma generateafter schema or config changes. That ensures the Prisma Client exists where your code expects it. - If you used a custom generator
outputinschema.prisma(for exampleoutput = "./generated/client"), verify the generated client path is present at runtime and that your imports are correct relative todist. Custom outputs require you to maintain correct relative paths after compilation — the GitHub issue above shows this exact situation where a custom generated path caused a require/import failure: https://github.com/prisma/prisma/issues/21066
Quick checks:
- Does
node_modules/.prisma/clientor your custom output exist afternpx prisma generate? - Is the generated client reachable from the compiled code? (Check
dist/...paths) - Is
dist/prisma.config.jspresent (if you rely on it)?
Debug checklist and quick fixes
Run these steps in order and confirm after each:
- Confirm the file that Node complains about actually exists:
ls -la dist/src | grep app.module(orls -la dist | grep app.module)- If there’s no
app.module.js, TypeScript didn’t compile it — fixinclude/rootDirand rebuild.
- If the files exist but Node still errors, check
package.json:
- If it contains
"type": "module", either remove it or move to an ESM migration (see above).
- Switch to CommonJS and rebuild (fastest fix):
- Update
tsconfig.json"module": "CommonJS"andincludethe Prisma config. rm -rf dist && npx tsc -p tsconfig.jsonnpx prisma generatenode dist/src/main.js(or yourstart:prodscript)
- If you must stay on ESM, verify:
tsconfig.jsonuses"module": "NodeNext"&"moduleResolution": "NodeNext".- All relative imports in source include
.jsso emitted code works in Node. - Handle Prisma client (CommonJS) via
createRequireor wrapper.
- Check generator/custom output paths:
- Open
prisma/schema.prisma. If you use:
generator client {
provider = "prisma-client-js"
output = "./generated/client"
}
make sure your runtime import points to ./generated/client (relative to compiled JS location), or use default output (node_modules) to avoid path headaches.
- Useful commands and script examples:
- Build:
npm run build(runstsc -p tsconfig.json) - Regenerate Prisma:
npx prisma generate - Run prod:
node dist/src/main.js - Check resolution at runtime:
node --trace-resolve dist/src/main.js(verbose resolution info)
- When in doubt, reproduce minimal case:
- Create a tiny Nest app, set
module: "ESNext", generate Prisma client, and observe failure; then switch to CommonJS and confirm success. This isolates whether Prisma’s client is the root cause.
If you want a direct pointer to the community explanation of this precise problem and the solution to change the module system, see the Stack Overflow discussion: https://stackoverflow.com/questions/79860717/prisma7-and-nestjs-module-conflicts
Sources
- Prisma7 and NestJS module conflicts — Stack Overflow
- NestJS:
Cannot find module './generated/client'when using custom output path — GitHub Issue #21066 · prisma/prisma - Nestjs with prisma cannot find module — Stack Overflow
- Cannot find module ‘generated/prisma’ or its corresponding type declarations — Stack Overflow
- NestJs: Cannot find module ‘generated/prisma’ — Reddit (discussion)
Conclusion
In short: the [ERR_MODULE_NOT_FOUND] Cannot find module 'app.module' after a Prisma 7 upgrade is almost always a module-format / build-output mismatch — your TypeScript is emitting ESM while Prisma 7’s client is CommonJS. The practical fix is to compile the backend as CommonJS ("module": "CommonJS"), include prisma.config.ts in the build so the config exists at runtime, run npx prisma generate, rebuild and run the compiled code. If you prefer to move to ESM, plan for a careful migration (package.json "type", .js extensions in imports, and a way to import Prisma’s CommonJS client).