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
- Provide a valid absolute URL with scheme: 'https://example.com'.
- Guard env-derived values: `metadataBase: process.env.SITE_URL ? new URL(process.env.SITE_URL) : undefined`.
- Set metadataBase only in the root layout and ensure it is defined in all environments (CI, preview, prod).
- 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
- Always include the scheme in metadataBase (https://).
- Guard env-derived metadataBase with existence + URL validity checks.
- Define metadataBase once in the root layout and ensure it is set in all environments.
- Use absolute URLs in metadata fields if metadataBase is unknown.
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
- Each route must start with '/': ${route}
- [inspect] ${route}: not an App Router document (no __next_f)
- Default export is missing in {resource_path}
- id property is required for every item returned from generat
- id property is required for every item returned from generat
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/e7f0a60b4c89d822.
Report an issue: GitHub.