DEV Community

koyablue
koyablue

Posted on

The Pitfalls of NEXT_PUBLIC_ Environment Variables

I ran into a tricky issue in my project where I was using this environment variable:

NEXT_PUBLIC_API_BASE_URL=https://~/api 
Enter fullscreen mode Exit fullscreen mode

This is the base URL for my API endpoints. Here's a super simplified version of how I used this variable:

 // In src/utils/env.ts export const getApiBaseUrl = (): string => { if (!process.env.NEXT_PUBLIC_API_BASE_URL) { throw new Error("NEXT_PUBLIC_API_BASE_URL is undefined"); } return process.env.NEXT_PUBLIC_API_BASE_URL; }; // In the API call function // This function is called in server components or server actions export const getEventByUuidService = async (uuid: string): Promise<Event> => { try { const res = await fetch(`${getApiBaseUrl()}/event/${uuid}`, { cache: "no-store" }); if (!res.ok) { throw new Error("Failed to get event by uuid"); } return (await res.json()).data; } catch (error) { throw error; } }; 
Enter fullscreen mode Exit fullscreen mode

Everything worked fine until I deployed it to Vercel. Then, I got this error in the runtime log:

TypeError: fetch failed at Object.fetch (node:internal/deps/undici/undici:11730:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { cause: Error: connect ECONNREFUSED 127.0.0.1:3000 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16) at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:128:17) { errno: -111, code: 'ECONNREFUSED', syscall: 'connect', address: '127.0.0.1', port: 3000 } } 
Enter fullscreen mode Exit fullscreen mode

Checking Chrome's network tab, I noticed that the request that should have gone to /api/events/{uuid} was instead sent to /events. It looked like NEXT_PUBLIC_API_BASE_URL was being ignored.

So, I did some digging and found this piece in the official docs:

To expose an environment variable to the browser, it must be prefixed with NEXT_PUBLIC_. However, these public environment variables will be inlined into the JavaScript bundle during the next build.

This means they can't be used on the server side, which I missed because my variable had the prefix.

After I dropped the NEXT_PUBLIC_ prefix, everything worked perfectly, no more errors.

So here is the conclusion.

  • Only use the NEXT_PUBLIC_ prefix for environment variables that need to be accessible on the client side.
  • For server side environment variables, skip the prefix.

Top comments (1)

Collapse
 
matei_alexandrustroescu_ profile image
Matei Alexandru Stroescu

Did you not read the docs?