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 (0)