Prisma 5.22 Query Engine not found on Vercel with Next.js 14 + pnpm + Turborepo monorepo

QuesI’m getting PrismaClientInitializationError: Prisma Client could not locate the Query Engine for runtime “rhel-openssl-3.0.x” on Vercel runtime. Build succeeds, runtime fails.
Stack:
Next.js 14.2.13 (App Router, standalone output via outputFileTracingRoot)
Prisma 5.22.0
pnpm 9.9.0 workspaces + Turborepo 2.8.17
Node 24.x (Vercel default)
Vercel Root Directory: apps/web
Monorepo structure:
apps/web ← Next.js app (Vercel Root Directory)
packages/db ← Prisma schema + generated client
packages/shared
packages/ui
Current configuration:
packages/db/prisma/schema.prisma:
prismagenerator client {
provider = “prisma-client-js”
previewFeatures = [“multiSchema”]
binaryTargets = [“native”, “rhel-openssl-3.0.x”]
}
packages/db/package.json:
json"scripts": {
“postinstall”: “prisma generate”
}
packages/db/src/index.ts:
tsimport { PrismaClient } from “@prisma/client”;
apps/web/next.config.mjs:
jsexperimental: {
outputFileTracingRoot: path.join(__dirname, ‘../../’),
serverComponentsExternalPackages: [‘@prisma/client’, ‘prisma’],
outputFileTracingIncludes: {
‘//': [
'../../node_modules/.pnpm/@prisma+client
/node_modules/@prisma/client/
/',
'../../node_modules/.pnpm/@prisma+engines
/node_modules/@prisma/engines/**/*’
],
},
}
apps/web/package.json:
json"build": “next build”
Build log shows success:
packages/db postinstall: :check_mark: Generated Prisma Client (v5.22.0) to
./../../node_modules/.pnpm/@prisma+client@5.22.0_prisma@5.22.0/node_modules/@prisma/client in 574ms
Runtime error:
Prisma Client could not locate the Query Engine for runtime “rhel-openssl-3.0.x”
Searched locations:
/var/task/node_modules/.pnpm/@prisma+client@5.22.0_prisma@5.22.0/node_modules/.prisma/client
/var/task/apps/web/.next/server
/vercel/path0/node_modules/.pnpm/@prisma+client@5.22.0_prisma@5.22.0/node_modules/@prisma/client
/var/task/apps/web/.prisma/client
/tmp/prisma-engines
What I’ve tried:
Setting output to ../../apps/web/generated/prisma — broke bundling
Setting PRISMA_QUERY_ENGINE_LIBRARY env var — broke install phase
Current setup with serverComponentsExternalPackages — build succeeds but engine not found at runtime
Various combinations of outputFileTracingIncludes glob patterns
The .so.node file is generated during build (confirmed in logs), but Next.js standalone output doesn’t include it in the function bundle at /var/task/.
What’s the correct configuration for Prisma to work in a pnpm Turborepo monorepo on Vercel with Next.js 14 standalone output?tions that get answered the fastest are the ones with relevant info included in the original post. Be sure to include all detail needed to let others see and understand the problem! →

This looks like a tracing problem more than a Prisma generate problem. The client is generated, but the native engine never makes it into the standalone function bundle.

I’d try two things first:

  1. pin Node to 20 or 22 instead of Vercel defaulting to 24
  2. stop relying on the pnpm virtual-store path in outputFileTracingIncludes. Generate the Prisma client inside a stable package-local output, then import that generated client from packages/db so Next can trace a real path instead of chasing node_modules/.pnpm/....

The key check is inside the built output: after next build, confirm the libquery_engine-rhel-openssl-3.0.x.so.node file exists under the standalone/server output that Vercel will actually upload. If it only exists back in /vercel/path0/node_modules/.pnpm/..., runtime will still fail.

If you have a public repo or can share the relevant package files, I can point to the exact config change.

Hi Moshe,

I’d treat this as “engine file not copied into the server bundle,” not as a failed prisma generate. Your logs show the client is generated, but the runtime search paths do not contain the libquery_engine-rhel-openssl-3.0.x.so.node file.

Two changes I’d try before more glob tweaking:

1. Pin Node to 20.x or 22.x instead of using Node 24 with Prisma 5.22 / Next 14.
2. Use Prisma’s Next.js monorepo workaround plugin so the engine files are copied during the server build.

Example for apps/web/next.config.mjs:

import path from "node:path"
import { fileURLToPath } from "node:url"
import { PrismaPlugin } from "@prisma/nextjs-monorepo-workaround-plugin"

const __dirname = path.dirname(fileURLToPath(import.meta.url))

const nextConfig = {
  output: "standalone",

  experimental: {
    outputFileTracingRoot: path.join(__dirname, "../../"),
    serverComponentsExternalPackages: ["@prisma/client", "prisma"],
  },

  webpack: (config, { isServer }) => {
    if (isServer) {
      config.plugins.push(new PrismaPlugin())
    }
    return config
  },
}

export default nextConfig

Then add the plugin in the workspace where the Next app builds:

pnpm add -D @prisma/nextjs-monorepo-workaround-plugin --filter web

After a local build, check the actual standalone output, not only the build log:

find apps/web/.next -name "libquery_engine-rhel-openssl-3.0.x.so.node"

If that file only exists under node_modules/.pnpm/... but not under .next/server or .next/standalone, Vercel will still fail at runtime.

Also, I’d avoid hardcoding .pnpm/@prisma+client... paths in outputFileTracingIncludes. Those paths are fragile because they can change with lockfile/package changes. If the plugin does not fix it, the next clean approach would be generating the Prisma client into a stable package-local output and importing from that generated path instead of relying on the virtual store path.