{"record":{"id":"e7f0a60b4c89d822","repo":"vercel/next.js","slug":"metadatabase-is-not-a-valid-url-metadatabase","errorCode":null,"errorMessage":"metadataBase is not a valid URL: ${metadataBase}","messagePattern":"metadataBase is not a valid URL: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/next/src/lib/metadata/resolve-metadata.ts","lineNumber":153,"sourceCode":"    return input.map((item) =>\n      convertUrlsToStrings(item)\n    ) as WithStringifiedURLs<T>\n  } else if (input && typeof input === 'object') {\n    const result: Record<string, unknown> = {}\n    for (const [key, value] of Object.entries(input)) {\n      result[key] = convertUrlsToStrings(value)\n    }\n    return result as WithStringifiedURLs<T>\n  }\n  return input as WithStringifiedURLs<T>\n}\n\nfunction normalizeMetadataBase(metadataBase: string | URL | null): URL | null {\n  if (typeof metadataBase === 'string') {\n    try {\n      metadataBase = new URL(metadataBase)\n    } catch {\n      throw new Error(`metadataBase is not a valid URL: ${metadataBase}`)\n    }\n  }\n  return metadataBase\n}\n\nasync function mergeStaticMetadata(\n  metadataBase: MetadataBaseURL,\n  source: Metadata | null,\n  target: ResolvedMetadata,\n  staticFilesMetadata: StaticMetadata,\n  metadataContext: MetadataContext,\n  titleTemplates: TitleTemplates,\n  leafSegmentStaticIcons: StaticIcons,\n  pathname: Promise<string>\n): Promise<ResolvedMetadata> {\n  if (!staticFilesMetadata) return target\n  const { icon, apple, openGraph, twitter, manifest } = staticFilesMetadata\n","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/lib/metadata/resolve-metadata.ts#L135-L171","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — app/layout.tsx\nexport const metadata = {\n  metadataBase: process.env.SITE_URL, // undefined -> 'undefined' string -> invalid\n}\n// after\nexport const metadata = {\n  metadataBase: process.env.SITE_URL\n    ? new URL(process.env.SITE_URL)\n    : undefined,\n}","handlingStrategy":"validation","validationCode":"function isValidMetadataBase(v: unknown): v is URL {\n  if (v == null) return false\n  try { new URL(v as string); return true } catch { return false }\n}\n// in generateMetadata:\nconst base = process.env.SITE_URL\nif (base && !isValidMetadataBase(base)) throw new Error('SITE_URL is not a valid URL')\nreturn { metadataBase: base ? new URL(base) : undefined }","typeGuard":"function isValidMetadataBase(v: unknown): v is string {\n  if (typeof v !== 'string') return false\n  try { new URL(v); return true } catch { return false }\n}","tryCatchPattern":"function safeMetadataBase(v?: string) {\n  if (!v) return undefined\n  try { return new URL(v) }\n  catch { console.warn('metadataBase invalid:', v); return undefined }\n}","preventionTips":["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."],"tags":["metadata","app-router","url","configuration"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}