Fix: "supabaseUrl is required" when your AI-built Next.js app fails to build
Short answer:
Error: supabaseUrl is required.duringnext buildusually means a file creates the Supabase client at the top of the file, and your Supabase variables are not set while the build runs. The smallest fix is to create the client inside a function, so it is only built when a request arrives. Verified on a synthetic app only. You may also need to add the variables in your host's settings (see "Not verified").
Prerequisites
- A Next.js app (App Router) that uses
@supabase/supabase-js. - Terminal access to the project, or your AI tool's code view.
- Know where your app is hosted (Vercel, Netlify, etc.) and where its environment variables are set.
- Never paste real keys into an AI chat. Use placeholders. Only the public "anon"/publishable key belongs in browser code; the secret/service-role key must never use a
NEXT_PUBLIC_name.
The exact error
From our reproduction (npx next build):
Collecting page data using 5 workers ...
Error: Failed to collect configuration for /api/waitlist
at ignore-listed frames {
[cause]: Error: supabaseUrl is required.
at module evaluation (app/api/waitlist/route.js:3:7)
1 | import { createClient } from "@supabase/supabase-js";
2 |
> 3 | const supabase = createClient(
| ^
...
> Build error occurred
Error: Failed to collect page data for /api/waitlist
Exit code: 1. Other people report the same text in public threads, for example vercel/next.js#69095 (a Vercel build on Next 14.2.3) and supabase/supabase#19377. We found these through web search; we did not measure how common it is.
Versions we used
| Item | Version |
|---|---|
| Node.js | 20.19.2 |
| npm | 11.21.0 |
| next | 16.4.2 (Turbopack build) |
| react | 19.3.1 |
| @supabase/supabase-js | 2.109.0 |
| OS | Linux, single machine |
Cause
Next.js loads your API route files during next build to collect page data. If a route file calls createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, ...) at the top level, that call runs during the build. If the variable is missing in that environment (not in .env.local, not set on the host, or misspelled), createClient throws, and the whole build fails. AI tools often generate this top-level pattern.
Smallest working fix
Move createClient into a function and call it inside the request handler. Nothing else changes.
Before (fails)
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
);
export async function POST(req) {
const { email } = await req.json();
const { error } = await supabase.from("waitlist").insert({ email });
return Response.json({ ok: !error });
}
After (builds)
import { createClient } from "@supabase/supabase-js";
function getSupabase() {
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
const key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
if (!url || !key) {
throw new Error("Missing NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_ANON_KEY");
}
return createClient(url, key);
}
export async function POST(req) {
try {
const { email } = await req.json();
const { error } = await getSupabase().from("waitlist").insert({ email });
return Response.json({ ok: !error });
} catch (e) {
return Response.json({ ok: false, error: e.message }, { status: 500 });
}
}
Copyable prompt for your AI coding tool
My Next.js build fails with "Error: supabaseUrl is required." Find every file (API routes, server actions, lib files) that calls createClient from @supabase/supabase-js at the top level of the module. Change each one so createClient is called inside a function (getSupabase) that reads process.env at request time, and throws a clear error naming the missing variable. Do not change variable names, do not add or print any key values, and do not touch anything else. Show me the diff.
Review the diff yourself. We did not test this prompt in any AI tool.
How we verified
All commands were run on 2026-10-18 in fix-01/before and fix-01/after, with no .env file and no Supabase variables set.
- Before:
npx next build→ failed with the error above, exit code 1. (Log:before-build.log) - After:
npx next build→ exit code 0. The output listedƒ /api/waitlistas a dynamic route. (Log:after-build.log) - After, runtime with missing keys: we ran
npx next startand sentPOST /api/waitlistwith a fake email. Response:HTTP/1.1 500with body{"ok":false,"error":"Missing NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_ANON_KEY"}. (Log:after-runtime.log)
Files: see the downloads below.
What this fix does and does not do
- It makes the build pass and gives a clear error at request time if keys are missing.
- It does not supply the missing keys. If your deployed app needs Supabase, the variables must still be set on your host, and changes to
NEXT_PUBLIC_variables generally need a new build to take effect (documented Next.js behavior; not re-tested here).
Not verified
- Anything against a real Supabase project: we never made a successful insert or any network call to Supabase.
- Vercel, Netlify or any hosting platform's build environment.
- Code generated by Lovable, Bolt, Cursor or v0. Our app is hand-written and synthetic, shaped like the pattern in the public reports.
- Other Next.js, Node or supabase-js versions, including Next 14 (seen in the public issue), the Pages Router, and Vite/React apps.
- Whether the AI prompt above produces a correct diff in any tool.
- The alternative workaround of setting placeholder variables in CI (seen in a public commit); we did not run it.
- Other causes of the same message: a misspelled or un-prefixed variable name, or a missing
.env.local. We did not reproduce those, though they give the same symptom.
Troubleshooting
- Build now passes but the live app errors with "Missing NEXT_PUBLIC_SUPABASE_URL…": the variable is not set on your host. Add it with the exact name, then redeploy.
- Still the same error after the fix: another file creates a client at the top level. Search the project for
createClient(. - Works locally, fails on the host:
.env.localis usually not committed, so the host never receives it. Check the host's environment variable settings.
Security notes
- Never put a secret or service-role key in a variable starting with
NEXT_PUBLIC_; it ships to every visitor's browser. - Do not paste real keys into AI chats, issues or screenshots.
Downloads
Synthetic example files from our test. No real keys or data.
- route.diff: Before/after diff of the route file
- before-route.js: Before: route file that fails to build
- after-route.js: After: route file that builds
- before-build.log.txt: Build log before the fix (exit 1)
- after-build.log.txt: Build log after the fix (exit 0)
- after-runtime.log.txt: Runtime check with missing keys (HTTP 500, clear message)