{"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/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/assets/fonts/core/create-get-font-file-url.ts#L1-L23","documentation":"experimental_getFontFileURL() asks the runtime font URL resolver to resolve the given URL; if the resolver returns null (the URL is not in the known set of generated font file URLs) or throws, the failure is wrapped as AstroError FontFileUrlNotFound. Only URLs obtained from the fontData object are valid inputs.","triggerScenarios":"Passing an arbitrary/hardcoded string to getFontFileURL() instead of a value from fontData; passing a URL after the font set changed (stale build); on-demand SSR where a slash-prefixed URL needs requestUrl but none was supplied.","commonSituations":"Hardcoding a font file URL; reusing a URL from a previous build after fonts changed; SSR calling getFontFileURL(url) without the second Astro.url argument.","solutions":["Pass only URLs that come from the fontData object returned by the fonts API.","For on-demand rendering, pass the request URL as the second argument: getFontFileURL(url, Astro.url).","Rebuild after changing fonts so the resolver's known URL set is up to date."],"exampleFix":"// before\nconst url = experimental_getFontFileURL('/fonts/roboto.woff2');\n// after - use the URL from fontData, and pass Astro.url in SSR\nconst url = experimental_getFontFileURL(fontData.fonts[0].url, Astro.url);","handlingStrategy":"validation","validationCode":"// Only pass URLs that belong to the fontData set, and always supply Astro.url in SSR.\nconst known = new Set(fontData.fonts.map((f) => f.url));\nif (!known.has(url)) throw new Error(`Unknown font URL \"${url}\". Use a URL from fontData.`);\nconst resolved = experimental_getFontFileURL(url, Astro.url);","typeGuard":"function isKnownFontUrl(fontData: { fonts: Array<{ url: string }> }, url: string): boolean {\n  return fontData.fonts.some((f) => f.url === url);\n}","tryCatchPattern":"try {\n  const u = experimental_getFontFileURL(url, Astro.url);\n} catch (e) {\n  if (e instanceof AstroError && e.name === 'FontFileUrlNotFound') {\n    // pick a valid URL from fontData and rebuild if fonts changed\n  } else throw e;\n}","preventionTips":["Pass only URLs sourced from the fontData object.","In on-demand rendering, always pass the request URL (Astro.url) as the second argument.","Rebuild after changing fonts so the resolver's URL set is current."],"tags":["fonts","experimental","url","ssr"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}