withastro/astro · error · Error

Server address unavailable, this should not happen. Open an

Error message

Server address unavailable, this should not happen. Open an issue.

What it means

Astro's experimental Fonts API serves font files in dev through a Vite middleware and during prerendering through a temporary Node HTTP server; experimental_getFontFileURL() turns the internal font path into an absolute URL by prefixing it with that server's origin. The origin normally comes from an AddressInfo snapshot baked into the virtual module 'virtual:astro:assets/fonts/runtime/font-file-url-resolver' when it is generated/evaluated. This error means that snapshot was null (the module was evaluated before any HTTP server emitted 'listening', e.g. an adapter's dep optimizer pre-bundled the fonts runtime, astro #17722) AND the caller did not pass a requestUrl as the second argument, so no origin could be derived. Astro throws rather than guessing because a wrong origin would silently produce broken font links; the message asks for an issue because it marks a race the runtime believes it has covered. Note the throw is wrapped by createGetFontFileURL into an AstroError named 'FontFileUrlNotFound', so this text usually appears as the cause of that error.

Source

Thrown at packages/astro/src/assets/fonts/infra/remote-runtime-font-file-url-resolver.ts:53

		if (!url.startsWith('/')) {
			if (this.#address) {
				url = new URL(url).pathname;
			} else {
				return url;
			}
		}
		if (this.#address) {
			const host =
				this.#address.family === 'IPv6' ? `[${this.#address.address}]` : this.#address.address;
			return `http://${host}:${this.#address.port}${url}`;
		}
		// Fallback when the server address was not available at module
		// load time (e.g. an adapter's dep optimizer pre-bundled the
		// font runtime before the HTTP server started listening, #17722).
		if (requestUrl) {
			return `${requestUrl.origin}${url}`;
		}
		throw new Error('Server address unavailable, this should not happen. Open an issue.');
	}
}

View on GitHub (pinned to 3578d45d34)

Solutions

  1. Pass the request URL as the second argument: experimental_getFontFileURL(url, Astro.url). The resolver then derives the origin from requestUrl.origin and never needs the server address.
  2. Update Astro to the latest release — the requestUrl fallback exists precisely for this race (#17722); older 5.x builds always threw in this situation.
  3. Restart the dev server and delete node_modules/.vite (and the adapter's pre-bundle cache) so the font runtime virtual module is regenerated after the HTTP server is listening, re-baking a non-null address.
  4. Only call experimental_getFontFileURL inside a request/render context (component frontmatter, API route), never at module top level where Astro.url is unavailable.
  5. If it still reproduces with a requestUrl passed and current Astro, open an issue on the withastro/astro repo as the message requests — it indicates an unhandled module-evaluation/server-bind race in an adapter.

Example fix

// before — single argument; relies on the dev-server address baked into the virtual module
import { experimental_getFontFileURL, fontData } from 'astro:assets/fonts/runtime';
const fileUrl = experimental_getFontFileURL(fontData.myFamily.regular[0].url);

// after — pass the request URL so the origin is derived from it when the
// server address was unavailable at module load time (#17722)
const fileUrl = experimental_getFontFileURL(fontData.myFamily.regular[0].url, Astro.url);
Defensive patterns

Strategy: validation

Validate before calling

// Before calling, verify you are in a request context and pass its URL —
// with a requestUrl present the resolver never reaches the throw.
const requestUrl = Astro.url;
if (!(requestUrl instanceof URL)) {
  throw new Error('experimental_getFontFileURL() must be called during a request, e.g. in component frontmatter');
}
const fileUrl = experimental_getFontFileURL(fontData.myFamily.regular[0].url, requestUrl);

Type guard

function isRequestUrl(value: unknown): value is URL {
  return value instanceof URL && /^https?:$/.test(value.protocol);
}

Try / catch

import { isAstroError } from 'astro/errors';

try {
  const fileUrl = experimental_getFontFileURL(fontUrl, Astro.url);
} catch (err) {
  if (isAstroError(err) && String((err.cause as Error)?.message ?? '').includes('Server address unavailable')) {
    // The dev-server address race: fall back to rendering without the
    // custom font file URL (or retry once the server is listening).
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling experimental_getFontFileURL(url) with a single argument (no requestUrl) while RemoteRuntimeFontFileUrlResolver was constructed with address: null — i.e. in 'astro dev' or prerendering when the font runtime virtual module was evaluated before the dev server's 'listening' event (vite-plugin-fonts.ts only captures serverAddress on listening) or before the prerender temp server existed. Classic repro: an adapter (Cloudflare/Netlify-style on-demand adapters) whose Vite optimizeDeps pre-bundles the fonts runtime ahead of server startup (#17722), or calling the helper at module top level / outside a request context where Astro.url cannot be passed. Reachable only for a known root-relative font URL: for assetsPrefix (non-slash) URLs the resolver returns early, and unknown URLs return null ('FontFileUrlNotFound' without this cause).

Common situations: Using the experimental fonts config (fonts: [...] in astro.config) together with the <Font /> component or experimental_getFontFileURL in dev, especially with an on-demand adapter installed. Running an older Astro version from before the #17722 requestUrl fallback was added, or a stale Vite dep cache (node_modules/.vite) still holding a pre-bundle generated before the server bound. Calling the helper in middleware, module scope, or a setup hook where no request URL exists.

Related errors


AI-assisted analysis of withastro/astro@3578d45d34 (2026-08-21). Data as JSON: /api/errors/54c1e1a2f16ea013. Report an issue: GitHub.