From 8ae013879bb0b63c771ac1558cbf730f977ed298 Mon Sep 17 00:00:00 2001 From: Randall Stillwell Date: Fri, 17 Apr 2026 16:15:41 -0500 Subject: [PATCH] Fix production build failure: lazy Prisma client initialization The Prisma client was constructed eagerly at module load, which called new URL(process.env.DATABASE_URL!) during Next.js 16 "Collect page data". When DATABASE_URL wasn't in the build environment (production), this threw TypeError: Invalid URL { input: 'undefined' } and failed the build for routes like /api/auth/forgot-password. Use a Proxy to defer client construction until the first property access, so build-time module evaluation no longer touches DATABASE_URL. Made-with: Cursor --- src/lib/db.ts | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/lib/db.ts b/src/lib/db.ts index 94faebb..52b2ca8 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -6,8 +6,14 @@ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined; }; -function createPrismaClient() { - const url = new URL(process.env.DATABASE_URL!); +function createPrismaClient(): PrismaClient { + const dbUrl = process.env.DATABASE_URL; + if (!dbUrl) { + throw new Error( + "DATABASE_URL is not set. Prisma client cannot be initialized." + ); + } + const url = new URL(dbUrl); url.searchParams.delete("sslmode"); const pool = new pg.Pool({ connectionString: url.toString(), @@ -18,6 +24,23 @@ function createPrismaClient() { return new PrismaClient({ adapter }); } -export const prisma = globalForPrisma.prisma ?? createPrismaClient(); +function getPrismaClient(): PrismaClient { + if (!globalForPrisma.prisma) { + globalForPrisma.prisma = createPrismaClient(); + } + return globalForPrisma.prisma; +} -if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; +// Lazy proxy so that importing `prisma` does NOT construct the client +// at module load. This lets Next.js collect page data during build even +// if DATABASE_URL isn't present in the build environment. +export const prisma = new Proxy({} as PrismaClient, { + get(_target, prop, receiver) { + const client = getPrismaClient(); + const value = Reflect.get(client, prop, receiver); + return typeof value === "function" ? value.bind(client) : value; + }, + has(_target, prop) { + return Reflect.has(getPrismaClient(), prop); + }, +}) as PrismaClient;