BuildWithMatija
  1. Home
  2. Blog
  3. Next.js
  4. Cannot find module ".prisma/client/default" — Prisma v7 on Next.js 16 + Turbopack Fix

Cannot find module ".prisma/client/default" — Prisma v7 on Next.js 16 + Turbopack Fix

Fix the module resolution error after upgrading Prisma to v7 in Next.js 16 with Turbopack — three required config…

1st December 2025·Updated on:3rd June 2026··
Next.js
Cannot find module ".prisma/client/default" — Prisma v7 on Next.js 16 + Turbopack Fix

⚡ Next.js Implementation Guides

In-depth Next.js guides covering App Router, RSC, ISR, and deployment. Get code examples, optimization checklists, and prompts to accelerate development.

No spam. Unsubscribe anytime.

Related Posts:

  • •How to Fix "Couldn't find next-intl config file" Error in Next.js 15
  • •searchParams Forces Dynamic Rendering in Next.js — Route Separation Fix
  • •Payload CMS + Next.js 16.2: Compatibility Status & Upgrade Guide
📄View markdown version
0

Frequently Asked Questions

About the author

Matija Žiberna

Matija Žiberna

Full-stack developer, co-founder

AboutResume

Self-taught full-stack developer sharing lessons from building software and startups.

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.

You might be interested in

How to Fix "Couldn't find next-intl config file" Error in Next.js 15
How to Fix "Couldn't find next-intl config file" Error in Next.js 15

23rd September 2025

searchParams Forces Dynamic Rendering in Next.js — Route Separation Fix
searchParams Forces Dynamic Rendering in Next.js — Route Separation Fix

5th October 2025

Payload CMS + Next.js 16.2: Compatibility Status & Upgrade Guide
Payload CMS + Next.js 16.2: Compatibility Status & Upgrade Guide

2nd December 2025

Contents

  • Understanding the Prisma v7 Changes
  • Upgrading the Prisma Packages
  • Configuring the Prisma Schema
  • Creating the Prisma Configuration File
  • Updating the Prisma Client Instantiation
  • The Triple-Layered Turbopack Fix
  • Generating and Testing the Client
  • Why This Configuration Works
  • Troubleshooting Common Errors
  • `error: The datasource.url property is required in your Prisma config file when using prisma migrate deploy`
  • `cannot find module 'prisma/config'`
  • `` `PrismaClient` needs to be constructed with a non-empty, valid `PrismaClientOptions` ``
  • `error: the datasource property url is no longer supported in schema files`
  • Verifying Your Migration
  • When This Is Not the Right Fix
  • Summary
On this page:
  • Understanding the Prisma v7 Changes
  • Upgrading the Prisma Packages
  • Configuring the Prisma Schema
  • Creating the Prisma Configuration File
  • Updating the Prisma Client Instantiation
Build with Matija logo

Build with Matija

Modern websites, content systems, and AI workflows built for long-term growth.

Services

  • Headless CMS Websites
  • Next.js & Headless CMS Advisory
  • AI Systems & Automation
  • Website & Content Audit

Resources

  • Case Studies
  • How I Work
  • Blog
  • CMS Hub
  • E-commerce Hub
  • Dashboard

Headless CMS

  • Payload CMS Developer
  • CMS Migration
  • Multi-Tenant CMS
  • Payload vs Sanity
  • Payload vs WordPress
  • Payload vs Contentful

Get in Touch

Ready to modernize your stack? Let's talk about what you're building.

Book a discovery callContact me →
© 2026Build with Matija•All rights reserved•Privacy Policy•Terms of Service
BuildWithMatija
Get In Touch

If you upgraded to Prisma v7 on Next.js 16 and hit Cannot find module '.prisma/client/default' during SSR, you're in the right place. This is for developers running Next.js 16 with Turbopack who need to complete the Prisma v6 → v7 migration without spending hours on module resolution errors. The official Prisma v7 migration guide doesn't address Turbopack compatibility — and the fix isn't just one change, it's three.

This guide walks through the complete migration from Prisma v6 to v7 (v7.4.2) with proper PostgreSQL adapter configuration. By the end, you'll have a working setup that's fully compatible with Next.js 16's Turbopack bundler.

TL;DR — 4 things to get Prisma v7 running on Next.js 16 + Turbopack:

  1. Keep provider = "prisma-client-js" in schema.prisma (not prisma-client)
  2. Add serverExternalPackages: ['@prisma/client', 'pg'] to next.config.ts
  3. Move all connection URLs from schema.prisma to prisma.config.ts
  4. Instantiate PrismaClient with an adapter — bare new PrismaClient() is invalid in v7

Understanding the Prisma v7 Changes

Prisma v7 introduces several breaking changes that fundamentally alter how the client is instantiated and configured. Here's a quick comparison of what changed:

Prisma v6Prisma v7
Generator providerprisma-client-jsprisma-client (new)
Connection configurl in schema.prismadatasource.url in prisma.config.ts
Client instantiationnew PrismaClient()new PrismaClient({ adapter })
Env loadingAuto-loaded from .envRequires import 'dotenv/config'
Query cachingNot availableBuilt-in (introduced in v7.4.0)

The most significant change is the requirement for driver adapters. In previous versions, Prisma handled database connections internally through its query engine. Version 7 moves to an adapter-based architecture where you explicitly provide a database driver, making the main Prisma Client leaner and more flexible.

Upgrading the Prisma Packages

The first step is upgrading both the Prisma CLI and client packages to version 7. The CLI is a dev dependency used for migrations and client generation, while the client package is the runtime dependency your application uses to query the database.

bash
pnpm add @prisma/client@7.4.2
pnpm add -D prisma@7.4.2

Along with Prisma itself, you'll need to install the PostgreSQL adapter and driver packages, as well as dotenv for environment variable management in the new config system.

bash
pnpm add @prisma/adapter-pg@^7.0.0 pg@^8.11.x dotenv
pnpm add -D @types/pg

These packages work together to provide the connection layer that Prisma v7 requires. The adapter translates between Prisma's query interface and the pg driver's native connection pooling.

Configuring the Prisma Schema

The schema file structure changes in Prisma v7. The datasource block no longer contains the database URL directly, as this configuration moves to the new prisma.config.ts file. This separation allows for more flexible configuration patterns and better alignment with TypeScript-based configuration systems.

Update your schema file to remove the URL configuration:

prisma
// File: prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
}

// Your models remain unchanged
model User {
  id    String @id @default(uuid())
  email String @unique
  name  String
  // ... rest of your schema
}

datasource db {
  provider = "postgresql"
}

// Your models remain unchanged
model User {
  id    String @id @default(uuid())
  email String @unique
  name  String
  // ... rest of your schema
}

The key change here is removing the url and directUrl properties from the datasource block. Notice we're using prisma-client-js as the provider rather than the new prisma-client name mentioned in the official docs. This is intentional and critical for Turbopack compatibility, which I'll explain in detail later.

Remove url, directUrl, and shadowDatabaseUrl from the datasource block — not just url. Leaving any of them will trigger: error: the datasource property url is no longer supported in schema files

Creating the Prisma Configuration File

Prisma v7 introduces a new TypeScript configuration file that handles runtime settings including database URLs, migration paths, and other CLI behaviors. This file uses the defineConfig helper and supports type-safe environment variable access.

import 'dotenv/config' at the top of this file is mandatory. Prisma v7 no longer auto-loads .env files for the CLI. If you skip this, environment variables will be undefined when running migrations. (Exception: Bun auto-loads env vars, so Bun users can omit it.)

Create the configuration file at your project root:

typescript
// File: prisma.config.ts

import 'dotenv/config';
import { defineConfig, env } from 'prisma/config';

export default defineConfig({
  schema: 'prisma/schema.prisma',
  datasource: {
    url: env('DATABASE_URL_UNPOOLED'),
  },
  migrations: {
    path: 'prisma/migrations',
  },
});

This configuration tells Prisma where to find your schema file and where to generate migrations. The env() helper provides type-safe access to environment variables. I'm using DATABASE_URL_UNPOOLED here because my project uses connection pooling with a service like Neon or Supabase, where the unpooled URL is needed for migrations. If you're running a standard PostgreSQL instance, you can use env('DATABASE_URL') instead.

If you're running prisma generate in a Docker build stage that doesn't have a live database available, you can bypass the strict env() helper and use process.env.DATABASE_URL! to avoid errors at build time when the variable may not be set:

typescript
// For CI/Docker build stages without a live database
export default defineConfig({
  schema: 'prisma/schema.prisma',
  datasource: {
    url: process.env.DATABASE_URL!,
  },
  migrations: {
    path: 'prisma/migrations',
  },
});

Updating the Prisma Client Instantiation

The way you create and export your Prisma Client changes significantly in version 7. Instead of directly instantiating PrismaClient, you now create a database adapter first, then pass it to the client constructor.

The way you create and export your Prisma Client changes significantly in version 7. Instead of directly instantiating PrismaClient, you now create a database adapter first, then pass it to the client constructor.

In Prisma v7, new PrismaClient() without arguments throws: PrismaClient needs to be constructed with a non-empty, valid PrismaClientOptions. The internal connection engine has been removed. You must pass { adapter } — there is no fallback.

Update your Prisma client file:
typescript
// File: lib/db/prisma.ts

import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
import pg from 'pg';

const { Pool } = pg;

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
  pool: pg.Pool | undefined;
};

// Create connection pool for the adapter
const pool = globalForPrisma.pool ?? new Pool({
  connectionString: process.env.DATABASE_URL,
});

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.pool = pool;
}

// Create Prisma adapter
const adapter = new PrismaPg(pool);

// Create Prisma Client with adapter
export const prisma =
  globalForPrisma.prisma ??
  new PrismaClient({
    adapter,
    log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
  });

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma;
}

export default prisma;

This code creates a PostgreSQL connection pool using the pg driver, wraps it in the Prisma adapter, and passes that adapter to the PrismaClient constructor. The global caching pattern prevents Next.js hot reload from creating multiple client instances during development. Notice we're caching both the pool and the prisma client to the global object, ensuring connection reuse across hot reloads.

The adapter acts as a bridge between Prisma's query interface and the native PostgreSQL driver. When Prisma needs to execute a query, it translates it into the format expected by the pg driver, which then handles the actual database communication through the connection pool.

The Triple-Layered Turbopack Fix

Here's where things get tricky. The official Prisma v7 migration guide recommends changing your generator provider from prisma-client-js to prisma-client. However, this creates a module resolution error with Next.js 16's Turbopack bundler. The new prisma-client provider generates client code in an ESM-optimized structure outside of node_modules, and Turbopack's module hashing loses reference to the internal runtime during SSR — trapping you in a Cannot find module '.prisma/client/default' loop.

The fix requires three changes, not one. Using only the generator workaround without the next.config.ts changes will still fail in some SSR configurations.

Switching to prisma-client-js alone is often not enough. All three steps below are required for reliable Turbopack compatibility.

Step 1 — Keep prisma-client-js as the generator provider

Your schema's generator block should look exactly like this:

prisma
generator client {
  provider = "prisma-client-js"
}

Do not add an output field, and do not use prisma-client as the provider.

Step 2 — Externalize Prisma packages in next.config.ts

Tell Next.js to treat these packages as server-external so Turbopack doesn't try to bundle them:

typescript
// File: next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  serverExternalPackages: ['@prisma/client', 'pg'],
};

export default nextConfig;

Step 3 — Add a Turbopack resolveAlias

If you're still hitting module resolution errors after steps 1 and 2, add an explicit alias pointing Turbopack to the generated Prisma client:

typescript
// File: next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  serverExternalPackages: ['@prisma/client', 'pg'],
  experimental: {
    turbo: {
      resolveAlias: {
        '.prisma/client/default': './node_modules/.prisma/client/default.js',
      },
    },
  },
};

export default nextConfig;

This is likely a temporary workaround that will be resolved as Turbopack matures and Prisma updates its generator to better support different bundler configurations.

Generating and Testing the Client

With your schema and configuration files updated, generate the Prisma client:

bash
npx prisma generate

You should see output indicating the client was generated successfully. The output will show the path where the client was created, typically in your node_modules under the .pnpm/@prisma+client@7.x.x/node_modules/@prisma/client directory when using pnpm.

If you have existing migrations, apply them with:

bash
npx prisma migrate deploy

For new migrations during development, use:

bash
npx prisma migrate dev --name your_migration_name

The migration commands now read their configuration from prisma.config.ts, using the database URL you specified there. This means you can have different URLs for migrations versus runtime queries, which is useful when working with connection pooling services.

Start your development server and test that database queries work correctly:

bash
pnpm dev

Navigate to any route that performs database operations. If you see the "Cannot find module" error at this point, double-check that your generator uses prisma-client-js and doesn't have an output path specified. That combination is what makes it work with Turbopack.

Why This Configuration Works

The reason prisma-client-js works while prisma-client doesn't comes down to module resolution paths and how different bundlers handle them. The newer prisma-client provider generates its output in an ESM-optimized structure outside of node_modules — which is great for modern bundlers but currently causes Turbopack to lose track of the generated client during the SSR phase. The older prisma-client-js provider generates the client in the traditional node_modules/.prisma/client location that Turbopack's resolution algorithm handles reliably.

The serverExternalPackages config tells Next.js not to bundle @prisma/client and pg at all — they're loaded at runtime from node_modules instead. This sidesteps the resolution conflict entirely. The resolveAlias is a further safety net that gives Turbopack an explicit path when its heuristic resolution fails.

Prisma v7's client is fully functional using the old provider name. The internal implementation is identical — it's purely a difference in output structure. By combining all three layers, you get all the performance improvements of v7 (including the query caching layer introduced in v7.4.0) while maintaining full compatibility with Next.js 16's bundler.

Troubleshooting Common Errors

Here are the most common errors developers hit during this migration and their exact fixes.

error: The datasource.url property is required in your Prisma config file when using prisma migrate deploy

This occurs during production deployments or Docker builds when the CLI can't resolve the connection string. Either prisma.config.ts wasn't copied into the build image, or the env() helper failed because the environment variable is undefined at that build stage.

Fix: In Docker environments, explicitly copy the config file in your Dockerfile:

dockerfile
COPY prisma.config.ts ./prisma.config.ts

If the error occurs during a prisma generate step that doesn't actually need a database connection, replace env('DATABASE_URL') with process.env.DATABASE_URL! in prisma.config.ts to bypass the strict env validation.

cannot find module 'prisma/config'

This almost always appears in monorepos or CI pipelines where Prisma is run via a global npx prisma install. The @prisma/config sub-module doesn't hoist correctly in that case.

Fix: Ensure prisma is installed as a local devDependency in the specific project workspace, not relied on globally:

bash
pnpm add -D prisma@7.4.2

Then run npx prisma from the project directory with the local install in scope.

`PrismaClient` needs to be constructed with a non-empty, valid `PrismaClientOptions`

This happens when you call new PrismaClient() without passing a driver adapter. In v7, the internal connection engine was removed — there is no fallback.

Fix: Always instantiate with an adapter:

typescript
import { Pool } from 'pg';
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from '@prisma/client';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const adapter = new PrismaPg(pool);
const prisma = new PrismaClient({ adapter });

error: the datasource property url is no longer supported in schema files

This is a hard breaking change in v7. The CLI rejects any schema that defines connection variables locally.

Fix: Remove url, directUrl, and shadowDatabaseUrl from your schema.prisma datasource block entirely — not just url. Then define them all inside the datasource object of prisma.config.ts.

Verifying Your Migration

After completing the migration, verify that everything works correctly by testing your application's database operations. Check that queries execute successfully, that connections are properly pooled, and that there are no runtime errors in your server logs. Pay particular attention to server actions and API routes, as these are where Prisma client usage is most common.

You should also verify that your development workflow still functions as expected. Hot reload should work without creating connection pool exhaustion, migrations should apply cleanly, and the Prisma Studio should connect properly if you use it.

When This Is Not the Right Fix

This guide targets the Cannot find module '.prisma/client/default' error caused by Turbopack's module resolution in Next.js 16. It does not apply if:

  • You are not using Turbopack — the standard webpack bundler handles Prisma module paths differently
  • The error appears in Jest or Vitest, not in the dev server or production build
  • You are on Prisma v5 or earlier — the adapter-based architecture described here is v7-specific
  • The module path in your error is something other than .prisma/client/default

If you're on Prisma v6 and not yet upgrading, the standard new PrismaClient() instantiation still works and the generator path issue does not apply.

Summary

Migrating to Prisma v7 on Next.js 16 with Turbopack requires more than just a package upgrade. The key changes are: keeping prisma-client-js as the generator provider, externalizing @prisma/client and pg via serverExternalPackages, moving all connection URLs to prisma.config.ts, and instantiating PrismaClient with the @prisma/adapter-pg adapter. Together these four changes give you stable Turbopack compatibility while unlocking all of v7's improvements — faster queries, smaller bundles, and the query caching layer introduced in v7.4.0.

If you're running into other Next.js 16 compatibility issues, the same Turbopack-related module resolution patterns come up with other packages too — see the fix for the "Couldn't find next-intl config file" error for a similar debugging approach. For i18n routing specifically, the next-intl proxy rename fix for Next.js 16 is another common breaking change that often surfaces in the same upgrade cycle. If you're also migrating your CMS layer, the Payload CMS & Next.js 16 compatibility guide covers the parallel upgrade path. If you're also using Payload CMS with its Drizzle/Postgres adapter and haven't switched from push mode yet, migrating Payload from push mode to migrations is the next production step. For self-hosting your full Next.js 16 stack, the self-hosted Payload + Next.js 16 deployment guide covers Docker and CI configuration.

If this migration is part of a larger Next.js 16 upgrade and you need senior support to get the architecture right, I work with a small number of teams at a time on this kind of production upgrade work.

If you run into issues during your migration or have questions about specific configuration scenarios, let me know in the comments.

Thanks, Matija