Fix this error · Supabase and Firebase
Fix: Error: supabaseUrl is required.
Fix "supabaseUrl is required." from createClient: missing NEXT_PUBLIC_ prefix, Vercel env not set for Preview, and the rebuild that inlines the value.
createClient from @supabase/supabase-js was called with an empty or undefined URL. The environment variable you pass in was not set where the code ran. In Next.js the usual causes are a missing NEXT_PUBLIC_ prefix on a variable read in the browser, a variable that Vercel has for Production but not for Preview, or a value added after the last build. Set the variable for the right environment and build again.
| Fact | Detail |
|---|---|
| Error | supabaseUrl is required. |
| Close relatives | supabaseKey is required. · Invalid supabaseUrl: Must be a valid HTTP or HTTPS URL. · @supabase/ssr: Your project's URL and API key are required to create a Supabase client! |
| Where you see it | Browser console, next build output, Vercel build or function logs, the terminal |
| Usual cause | process.env.NEXT_PUBLIC_SUPABASE_URL is undefined at build time or in that environment |
| Usual fix | Set the variable for every environment that builds the app, then rebuild or redeploy |
| BugTape catches it | At request time on the server, and in the browser after BugTape starts. A failure at build time is only in your build log |
What the error means
supabase-js validates the URL before it creates anything. It trims the value, and when nothing is left it throws Error('supabaseUrl is required.'). A value without http:// or https:// throws Invalid supabaseUrl: Must be a valid HTTP or HTTPS URL. A missing key throws supabaseKey is required.
@supabase/ssr checks both values first and throws its own message. createBrowserClient says @supabase/ssr: Your project's URL and API key are required to create a Supabase client! and createServerClient says Your project's URL and Key are required to create a Supabase client! The cause and the fix are the same.
The ! in process.env.NEXT_PUBLIC_SUPABASE_URL! only tells TypeScript to stop warning. At runtime the value is still undefined.
Common causes
- The variable is not set in the environment that built the app. On Vercel each variable is set for Production, Preview, Development or custom environments. A variable only in Production is missing from every preview deployment.
- The variable was added after the last deployment. Vercel applies environment variable changes only to new deployments. Next.js inlines
NEXT_PUBLIC_values into the browser bundle at build time, so a new value needs a new build. - The browser reads a variable without the
NEXT_PUBLIC_prefix.SUPABASE_URLexists on the server and is undefined in the browser. - A dynamic lookup.
process.env[name]orconst env = process.env; env.NEXT_PUBLIC_SUPABASE_URLis not inlined, so it is undefined in the browser. - The
.envfile is in the wrong place or has the wrong name. Next.js loads.env*files only from the project root. Files insidesrc/are ignored..env.localis not loaded whenNODE_ENVistest. - One Docker image or build is promoted to several environments.
NEXT_PUBLIC_values are frozen at build time, so the runtime environment cannot change them. - Vite or another bundler. Vite exposes only variables prefixed with
VITE_throughimport.meta.env, soprocess.env.SUPABASE_URLis undefined there.
How to fix it
Set both variables with the names the code reads
# .env.local in the project root, next to package.json
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-publishable-keyRestart next dev after you change .env.local. The publishable key is safe in the browser. The secret key is not, and must never get a NEXT_PUBLIC_ prefix.
Set them for every Vercel environment and redeploy
vercel env add NEXT_PUBLIC_SUPABASE_URL production
vercel env add NEXT_PUBLIC_SUPABASE_URL preview
vercel env add NEXT_PUBLIC_SUPABASE_URL development
vercel env pull .env.local # copy the Development values to your machineThen start a new deployment. The existing ones keep the values they were built with.
Read the variables with static names
Write each variable out in full so Next.js can replace it at build time.
// lib/supabase/env.ts
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
const key = process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY;
if (!url || !key) {
throw new Error(
'Missing NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY. ' +
'Set them for this environment and rebuild.',
);
}
export const supabaseUrl = url;
export const supabasePublishableKey = key;A clear message names the variable, which saves a search the next time it happens.
Create the client inside a function
A client created at the top of a module runs when the module is imported, which can be during next build or before anything else on the page has loaded. Creating it in a function moves the error to the first real use.
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';
import { supabaseUrl, supabasePublishableKey } from './env';
export function createClient() {
return createBrowserClient(supabaseUrl, supabasePublishableKey);
}Use the Vite prefix in Vite apps
import { createClient } from '@supabase/supabase-js';
export const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
);How to catch it in production with BugTape
Where this error happens decides whether BugTape sees it.
- During
next build. When a page is prerendered, the error fails the build. Nothing is running yet, so no SDK reports it. Read the build log. - On the server at request time. The Node.js SDK reports errors thrown in pages, Route Handlers, Server Actions and the proxy through Next.js
onRequestError, on the Node.js runtime. The Edge runtime is not supported. - In the browser. The browser SDK reports uncaught errors as soon as
init()has run. A client created at the top of a module that loads with the first page can throw before BugTape starts, and that one is missed. A client created inside a function, on first use, is reported with the page URL and the steps before it.
Wire the server side once:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') (await import('@bugtape/node')).init({ service: 'web' });
}
export async function onRequestError(...args: Parameters<typeof import('@bugtape/node').captureRequestError>) {
if (process.env.NEXT_RUNTIME === 'nodejs') await (await import('@bugtape/node')).captureRequestError(...args);
}For a missing variable you detect yourself, report it and keep the page usable. In the browser, reportError(err) fires the same window error event the SDK listens for. On the server, call bugtape.captureException(err).
Every visitor to a broken deployment hits the same line, so the reports group into one issue with a count. Set release (on Vercel, VERCEL_GIT_COMMIT_SHA, which the Node.js SDK reads on its own) so you can see which deployment is missing the value, and a fix that does not hold reopens as a regression. Your coding agent can read the issue over MCP (npx -y bugtape connect claude, or cursor or codex). You review the pull request.
FAQ
Why does it work locally but fail on Vercel?
Your machine reads .env.local, which Vercel never sees. Add the variables in the project settings for each environment you deploy, then start a new deployment.
Why does it work in production but fail in preview deployments?
The variable is set only for Production. Preview deployments use the Preview environment. Add the variable there, or for a specific branch, and redeploy.
I set the variable but the error is still there. Why?
NEXT_PUBLIC_ values are copied into the JavaScript bundle when the app is built. Changing the variable does not change a build that already exists. Start a new build. Locally, restart next dev.
Is it safe to put the Supabase URL and key in NEXT_PUBLIC_ variables?
The project URL and the publishable (anon) key are meant for the browser. Your data is protected by row-level security policies. The secret key, or the legacy service_role key, bypasses those policies and must stay in server-only variables.
Sources
- supabase-js source: lib/helpers.ts and SupabaseClient.ts (exact messages), checked 2 Nov 2026.
- @supabase/ssr source: createBrowserClient.ts and createServerClient.ts, checked 2 Nov 2026.
- Next.js: Environment variables (
NEXT_PUBLIC_inlined at build time, dynamic lookups, load order), checked 2 Nov 2026. - Vercel: Environment variables (environments, changes apply to new deployments,
vercel env pull), checked 2 Nov 2026. - Vite: Env variables and modes, checked 2 Nov 2026.
Related errors
- Supabase Auth session missing:
AuthSessionMissingError: Auth session missing! - ReferenceError: window is not defined:
ReferenceError: window is not defined - Vercel FUNCTION_INVOCATION_FAILED:
500: INTERNAL_SERVER_ERROR Code: FUNCTION_INVOCATION_FAILED - Supabase row-level security violation:
new row violates row-level security policy for table - Firebase missing or insufficient permissions:
FirebaseError: Missing or insufficient permissions.
All guides: Fix an error.
Start free. Free plan · No credit card · Set up in minutes. Or try the live demo first.