vercel/next.js · error · Error

metadataBase is not a valid URL: ${metadataBase}

Error message

metadataBase is not a valid URL: ${metadataBase}

What it means

Thrown by normalizeMetadataBase() when the metadata.metadataBase value is a string that cannot be parsed by the URL constructor. metadataBase is the absolute origin used to resolve relative metadata URLs (OpenGraph images, canonical, etc.); an invalid base breaks all relative URL resolution, so Next.js fails fast at metadata-merge time.

Source

Thrown at packages/next/src/lib/metadata/resolve-metadata.ts:153

    return input.map((item) =>
      convertUrlsToStrings(item)
    ) as WithStringifiedURLs<T>
  } else if (input && typeof input === 'object') {
    const result: Record<string, unknown> = {}
    for (const [key, value] of Object.entries(input)) {
      result[key] = convertUrlsToStrings(value)
    }
    return result as WithStringifiedURLs<T>
  }
  return input as WithStringifiedURLs<T>
}

function normalizeMetadataBase(metadataBase: string | URL | null): URL | null {
  if (typeof metadataBase === 'string') {
    try {
      metadataBase = new URL(metadataBase)
    } catch {
      throw new Error(`metadataBase is not a valid URL: ${metadataBase}`)
    }
  }
  return metadataBase
}

async function mergeStaticMetadata(
  metadataBase: MetadataBaseURL,
  source: Metadata | null,
  target: ResolvedMetadata,
  staticFilesMetadata: StaticMetadata,
  metadataContext: MetadataContext,
  titleTemplates: TitleTemplates,
  leafSegmentStaticIcons: StaticIcons,
  pathname: Promise<string>
): Promise<ResolvedMetadata> {
  if (!staticFilesMetadata) return target
  const { icon, apple, openGraph, twitter, manifest } = staticFilesMetadata

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Provide a valid absolute URL with scheme: 'https://example.com'.
  2. Guard env-derived values: `metadataBase: process.env.SITE_URL ? new URL(process.env.SITE_URL) : undefined`.
  3. Set metadataBase only in the root layout and ensure it is defined in all environments (CI, preview, prod).
  4. If metadataBase is genuinely unknown (e.g. local dev), leave it undefined and use absolute URLs in metadata fields.

Example fix

// before — app/layout.tsx
export const metadata = {
  metadataBase: process.env.SITE_URL, // undefined -> 'undefined' string -> invalid
}
// after
export const metadata = {
  metadataBase: process.env.SITE_URL
    ? new URL(process.env.SITE_URL)
    : undefined,
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidMetadataBase(v: unknown): v is URL {
  if (v == null) return false
  try { new URL(v as string); return true } catch { return false }
}
// in generateMetadata:
const base = process.env.SITE_URL
if (base && !isValidMetadataBase(base)) throw new Error('SITE_URL is not a valid URL')
return { metadataBase: base ? new URL(base) : undefined }

Type guard

function isValidMetadataBase(v: unknown): v is string {
  if (typeof v !== 'string') return false
  try { new URL(v); return true } catch { return false }
}

Try / catch

function safeMetadataBase(v?: string) {
  if (!v) return undefined
  try { return new URL(v) }
  catch { console.warn('metadataBase invalid:', v); return undefined }
}

Prevention

When it happens

Trigger: A layout or page exports `metadata` (or generateMetadata returns) with a metadataBase string that is not a valid absolute URL — missing protocol (example.com), typos, placeholders left in (process.env.URL unset yielding 'undefined'), or a relative path. normalizeMetadataBase wraps `new URL(metadataBase)` in try/catch and re-throws this message.

Common situations: Setting metadataBase from an env var that is undefined in the build environment; forgetting the https:// scheme; copy-pasting a hostname without protocol; local dev with a placeholder; or generating metadataBase dynamically and yielding an empty string.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/e7f0a60b4c89d822. Report an issue: GitHub.