{"record":{"id":"f79bea38927df72a","repo":"withastro/astro","slug":"fontfileurlnotfound","errorCode":"FontFileUrlNotFound","errorMessage":"The `\"${url}\"` URL passed to the `experimental_getFontFileURL()` function is invalid.","messagePattern":"The `\"(.+?)\"` URL passed to the `experimental_getFontFileURL\\(\\)` function is invalid\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/assets/fonts/core/create-get-font-file-url.ts","lineNumber":13,"sourceCode":"import { AstroError, AstroErrorData } from '../../../core/errors/index.js';\nimport type { RuntimeFontFileUrlResolver } from '../definitions.js';\n\nexport function createGetFontFileURL(runtimeFontFileUrlResolver: RuntimeFontFileUrlResolver) {\n\treturn function getFontFileURL(url: string, requestUrl?: URL): string {\n\t\ttry {\n\t\t\tconst result = runtimeFontFileUrlResolver.resolve(url, requestUrl);\n\t\t\tif (result === null) {\n\t\t\t\tthrow new Error('Not found');\n\t\t\t}\n\t\t\treturn result;\n\t\t} catch (cause) {\n\t\t\tthrow new AstroError(\n\t\t\t\t{\n\t\t\t\t\t...AstroErrorData.FontFileUrlNotFound,\n\t\t\t\t\tmessage: AstroErrorData.FontFileUrlNotFound.message(url),\n\t\t\t\t},\n\t\t\t\t{ cause },\n\t\t\t);\n\t\t}\n\t};\n}\n","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/assets/fonts/core/create-get-font-file-url.ts#L1-L23","documentation":"Part of the experimental Fonts API. `experimental_getFontFileURL(url, requestUrl?)` (packages/astro/src/assets/fonts/runtime.ts) can only resolve URLs that the fonts pipeline registered at build time; the underlying `runtimeFontFileUrlResolver.resolve()` returns null for anything else, which is rethrown as `FontFileUrlNotFound` with the failed resolution as `cause`.","triggerScenarios":"Calling `experimental_getFontFileURL()` with a hand-written path or a URL that was not obtained from the `fontData` object — e.g. `experimental_getFontFileURL('/fonts/my-font.woff2')` — or with a URL for a family that was not included in the `fonts` config.","commonSituations":"Experimenting with the experimental fonts API and guessing the URL shape; copy-pasting a font path from `dist/`; a family silently dropped from config so its URLs were never registered.","solutions":["Only pass URLs that come from the `fontData` object (keyed by CSS variable) exported by the experimental Fonts API — never hand-written paths.","Confirm the family is actually present in your `fonts` configuration and builds without warnings, so its URLs get registered.","Log the available entries of `fontData` once to see the exact URL keys the resolver knows about."],"exampleFix":"// before — hand-written URL, never registered by the fonts pipeline\nconst url = experimental_getFontFileURL('/fonts/noto-regular.woff2');\n\n// after — URL obtained from fontData\nconst { fonts } = fontData; // keyed by cssVariable\nconst url = experimental_getFontFileURL(fonts['--my-noto'].urls[0], Astro.url);","handlingStrategy":"validation","validationCode":"// only call the resolver with URLs the pipeline registered\nconst knownUrls: string[] = Object.values(fontData).flatMap((entry: any) =>\n  Object.values(entry.variants ?? {}).flatMap((v: any) => Object.values(v)),\n).filter((u): u is string => typeof u === 'string');\nif (!knownUrls.includes(candidateUrl)) {\n  throw new Error(`URL not registered by the fonts pipeline: ${candidateUrl}`);\n}","typeGuard":"const isRegisteredFontUrl = (url: string, fontData: Record<string, any>): boolean =>\n  Object.values(fontData).some((entry) =>\n    JSON.stringify(entry).includes(url),\n  );","tryCatchPattern":"try {\n  const fileUrl = experimental_getFontFileURL(url, Astro.url);\n} catch (err) {\n  if (err instanceof AstroError && err.name === 'FontFileUrlNotFound') {\n    // fall back to the family's primary URL or skip the font-dependent render\n  } else throw err;\n}","preventionTips":["Derive every URL you pass from fontData; never concatenate paths by hand.","Log Object.keys(fontData) once during onboarding to learn the registered keys.","Keep the fonts config and the consuming components in the same PR so registrations stay in sync."],"tags":["fonts","experimental","fonts-api"],"backgroundTag":"unregistered-asset-url","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}