Skip to content

Fix Next.js metadata base TypeError with undefined environment variable

fix

Next.js metadata throws TypeError: Invalid URL when NEXT_PUBLIC_APP_URL environment variable is undefined at build time

nextjsmetadataenvironment-variables
23 views

Problem

Next.js throws a TypeError at build time when the metadataBase URL is constructed from an undefined environment variable:

TypeError: Invalid URL: undefined
    at new URL (<anonymous>)
    at Module.default [as generateMetadata] (app/layout.tsx:12:18)
    at resolveMetadata (next/dist/lib/metadata/resolve-metadata.js:1:1)

The metadata export in layout.tsx that causes the crash:

// app/layout.tsx
export const metadata: Metadata = {
  metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL!),
  //                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  //                    undefined at build time -> TypeError
  title: "My App",
  description: "My application",
};

Solution

Option 1: Use nullish coalescing with a fallback URL (recommended)

// app/layout.tsx
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000";

export const metadata: Metadata = {
  metadataBase: new URL(BASE_URL),
  title: "My App",
  description: "My application",
};

Option 2: Use Vercel system environment variables as fallback

// app/layout.tsx
const BASE_URL =
  process.env.NEXT_PUBLIC_APP_URL ??
  (process.env.VERCEL_PROJECT_PRODUCTION_URL
    ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
    : "http://localhost:3000");

export const metadata: Metadata = {
  metadataBase: new URL(BASE_URL),
  title: "My App",
  description: "My application",
};

Why It Works

NEXT_PUBLIC_ environment variables are inlined at build time by Next.js. If the variable is not set in the build environment, it evaluates to undefined. Calling new URL(undefined) throws a TypeError because undefined is not a valid URL string. The nullish coalescing operator (??) provides a safe fallback so the URL constructor always receives a valid string, whether or not the environment variable is defined.

Context

  • Next.js 14+ metadata API with metadataBase for resolving relative Open Graph and canonical URLs
  • Common in Vercel and Netlify deployments where .env.local is not available during CI builds
  • On Vercel, VERCEL_URL (preview deployment URL) and VERCEL_PROJECT_PRODUCTION_URL (production domain) are automatically set as system environment variables -- but they are not prefixed with NEXT_PUBLIC_, so they are only available server-side
  • Set NEXT_PUBLIC_APP_URL in your hosting provider's environment variable settings for production builds
  • The same pattern applies to any new URL() call that depends on environment variables, such as API base URLs or OAuth redirect URIs
About this share
Contributormblode
Repositorymblode/shares
CreatedFeb 9, 2026
Environmentnextjs 14+
View on GitHub