withastro/astro · error · AstroError
CannotFetchFontFile
CannotFetchFontFile
Error message
An error occurred while fetching the font file from ${url}. What it means
Thrown by CachedFontFetcher.fetch when retrieving a font file fails. The fetcher first tries to read an absolute path from disk via readFile; otherwise it issues an HTTP request. Any failure (non-2xx status, network error, filesystem read error, or an unreadable response body) is wrapped in an AstroError with code CannotFetchFontFile, preserving the original cause.
Source
Thrown at packages/astro/src/assets/fonts/infra/cached-font-fetcher.ts:47
}
const data = await cb();
await storage.setItemRaw(key, data);
return data;
}
async fetch({ id, url, init }: FontFileData): Promise<Buffer> {
return await this.#cache(this.#storage, id, async () => {
try {
if (isAbsolute(url)) {
return await this.#readFile(url);
}
const response = await this.#fetch(url, init ?? undefined);
if (!response.ok) {
throw new Error(`Response was not successful, received status code ${response.status}`);
}
return Buffer.from(await response.arrayBuffer());
} catch (cause) {
throw new AstroError(
{
...AstroErrorData.CannotFetchFontFile,
message: AstroErrorData.CannotFetchFontFile.message(url),
},
{ cause },
);
}
});
}
}
View on GitHub (pinned to d081033d5f)
Solutions
- Check network egress from the build/host environment to the font source host (curl the exact url from the error).
- Verify the URL is correct and the font family/weight exists on the remote provider; a 404/403 will trigger this.
- If the URL is a local absolute path, confirm the file exists and is readable by the build process.
- Pass a custom init (RequestInit) with headers/proxy if behind a corporate proxy or needing a User-Agent.
- Inspect the `cause` on the thrown AstroError for the underlying fetch/filesystem error detail.
Example fix
// before
experimentalSvgFonts({ families: [{ name: 'My Font', weight: 999 }] })
// after - verify the exact URL resolves before building
const res = await fetch('https://fonts.gstatic.com/.../myfont.woff2');
if (!res.ok) throw new Error(`font ${res.status}`); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the URL before fetching
import { isAbsolute } from 'node:path';
function isValidFontUrl(url: string): boolean {
try {
if (isAbsolute(url)) return true; // local path handled by fs
const u = new URL(url);
return u.protocol === 'http:' || u.protocol === 'https:';
} catch { return false; }
} Try / catch
try {
const buf = await fontFetcher.fetch({ id, url });
} catch (e) {
if (e instanceof AstroError && e.code === 'CannotFetchFontFile') {
// inspect e.cause for the underlying fetch/fs error; retry with a fallback provider
}
throw e;
} Prevention
- Smoke-test font URLs (curl -I) in the build environment before building.
- Pin font provider URLs to a stable CDN host.
- Cache font files locally as a fallback for airgapped/offline builds.
- Ensure the build host has egress to the font provider domain.
When it happens
Trigger: Calling fetch({ id, url, init }) where url is a remote URL that returns a non-OK status (response.ok is false), or the network call rejects, or url is an absolute filesystem path that readFileSync cannot open. Any exception thrown inside the try block (including a thrown Error for status codes) is caught and rethrown as CannotFetchFontFile with the offending url interpolated.
Common situations: A font provider URL is unreachable due to a corporate proxy, a typo'd family/weight URL, the font CDN returning 403/404, the build host lacking egress to fonts.googleapis.com / fonts.gstatic.com, or a local file path that does not exist or has wrong permissions during build.
Related errors
- CannotDetermineWeightAndStyleFromFontFile
- UnknownFilesystemError
- CannotExtractFontType
- UnknownFilesystemError
- the prerender server responded ${response.status} ${response
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/fd2db7da02a72fd8.
Report an issue: GitHub.