EXT nextjs configuration_error ai_generated true

Error: Environment variable 'X' is not available on the client. Use NEXT_PUBLIC_ prefix.

ID: nextjs/env-var-client-access

Also available as: JSON · Markdown
93%Fix Rate
94%Confidence
80Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
14 active

Root Cause

Next.js only exposes environment variables to client-side (browser) code if they are prefixed with NEXT_PUBLIC_. Variables without this prefix are available only in server-side code (API routes, getServerSideProps, Server Components, Server Actions). This is a security feature to prevent accidental leaking of secrets like API keys, database credentials, and tokens to the browser bundle. The error manifests as undefined values when accessing process.env.MY_VAR in client components, or as an explicit error when Next.js detects client-side access attempts. Fix by either adding the NEXT_PUBLIC_ prefix for truly public values, or restructuring the code to access the variable server-side and pass the result to the client.

generic

Workarounds

  1. 95% success Prefix truly public (non-sensitive) variables with NEXT_PUBLIC_ in .env files
    Rename the variable in your .env file: NEXT_PUBLIC_API_URL=https://api.example.com, NEXT_PUBLIC_ANALYTICS_ID=UA-12345. Then access it as process.env.NEXT_PUBLIC_API_URL in client components. Important: you must restart the Next.js dev server after changing .env files. Only use this for non-sensitive values like public API endpoints, feature flags, or analytics IDs. Never prefix database URLs, API secrets, or auth tokens with NEXT_PUBLIC_
  2. 91% success Create an API route or Server Action that accesses the server-side variable and returns the result
    Create a server endpoint that accesses the variable: // app/api/config/route.ts: export async function GET() { return Response.json({ apiUrl: process.env.INTERNAL_API_URL }); }. Call it from the client: const res = await fetch('/api/config'); const { apiUrl } = await res.json(); For Server Actions: // actions.ts: 'use server'; export async function getConfig() { return { featureEnabled: process.env.FEATURE_FLAG === 'true' }; }. This keeps the raw secret server-side while exposing only the computed result
  3. 92% success Pass server environment values as props from Server Components to Client Components
    Access the env var in a Server Component and pass it as a prop: // app/page.tsx (Server Component): import { ClientDashboard } from './ClientDashboard'; export default function Page() { const apiUrl = process.env.INTERNAL_API_URL; return <ClientDashboard apiUrl={apiUrl!} />; } // ClientDashboard.tsx: 'use client'; export function ClientDashboard({ apiUrl }: { apiUrl: string }) { /* use apiUrl */ }. This keeps the variable out of the client bundle while making the value available. Note: the value will still be visible in the HTML/RSC payload, so do not pass actual secrets this way - only pass derived/safe values

Dead Ends

Common approaches that don't work:

  1. Using process.env directly in client components and expecting runtime variable access 95% fail

    Next.js performs static string replacement of process.env.NEXT_PUBLIC_* at build time using webpack DefinePlugin. Non-prefixed variables are never included in the client bundle. process.env on the client is an empty object - there is no runtime environment variable access in the browser. Even if you somehow inject process.env at runtime (e.g., via a polyfill), Next.js build optimization has already replaced the references

  2. Adding the secret/sensitive variable with NEXT_PUBLIC_ prefix to make it accessible on the client 90% fail

    NEXT_PUBLIC_ variables are inlined into the JavaScript bundle at build time and are visible to anyone who inspects the page source or network requests. Adding NEXT_PUBLIC_ to database URLs, API secret keys, auth tokens, or any sensitive value exposes them publicly. This is a security vulnerability, not a fix. The variable was intentionally server-only to protect it

  3. Using dynamic import or eval to access process.env at runtime in client code 95% fail

    The environment variable replacement happens at compile time during the webpack build, not at runtime. Dynamic import delays module loading but the module is still compiled with the same build-time replacements. eval('process.env.MY_VAR') will fail because process.env is not available in the browser environment. These approaches add complexity without solving the fundamental issue that server environment variables are not shipped to the client

Error Chain

Leads to:
Preceded by:
Frequently confused with: