withastro/astro · error · Error

Unable to resolve [${specifier}]

Error message

Unable to resolve [${specifier}]

What it means

`productionEnvironment.resolve` maps an entry specifier (for example a client script or style entry emitted during build) through `manifest.entryModules` to its bundled path, then turns that into an asset link honoring `base` and `assetsPrefix`. If the specifier is not a key in `entryModules`, it throws `Unable to resolve [<specifier>]` — the requested entry was never emitted into this build's manifest.

Source

Thrown at packages/astro/src/core/environment/production.ts:78

	manifest: SSRManifest,
	routeData: RouteData,
): Promise<ComponentInstance> {
	const module = await getModuleForRoute(manifest, routeData);
	return module.page();
}

/**
 * The production / bundled environment — the default when nothing is
 * registered. A stateless module constant derived from the manifest alone.
 */
export const productionEnvironment: RenderEnvironment = {
	name: 'production',
	runtimeMode: 'production',
	defaultStreaming: () => true,

	async resolve(manifest: SSRManifest, specifier: string): Promise<string> {
		if (!(specifier in manifest.entryModules)) {
			throw new Error(`Unable to resolve [${specifier}]`);
		}
		const bundlePath = manifest.entryModules[specifier];
		if (bundlePath.startsWith('data:') || bundlePath.length === 0) {
			return bundlePath;
		} else {
			return createAssetLink(bundlePath, manifest.base, manifest.assetsPrefix);
		}
	},

	async headElements(manifest: SSRManifest, routeData: RouteData): Promise<HeadElements> {
		const { assetsPrefix, base } = manifest;
		const routeInfo = manifest.routes.find((route) => route.routeData.route === routeData.route);
		// may be used in the future for handling rel=modulepreload, rel=icon, rel=manifest etc.
		const links = new Set<never>();
		const scripts = new Set<SSRElement>();
		const styles = createStylesheetElementSet(routeInfo?.styles ?? [], base, assetsPrefix);

		for (const script of routeInfo?.scripts ?? []) {

View on GitHub (pinned to 52e6c34790)

Solutions

  1. Rebuild and redeploy server + client output together so `entryModules` matches the assets on disk.
  2. Grep the built SSR manifest for the specifier to confirm whether the build emitted it at all.
  3. If writing an integration, only resolve specifiers that were registered during the same build; guard unknown ones.
  4. Check that conditional emission (route filters, `output` flags) did not skip the entry your code unconditionally resolves.

Example fix

// before — resolving an entry the build never emitted
const url = await env.resolve(manifest, 'src/scripts/quantum.js'); // throws

// after — only resolve entries present in the manifest
if ('src/scripts/quantum.js' in manifest.entryModules) {
  const url = await env.resolve(manifest, 'src/scripts/quantum.js');
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Before resolving an asset entry, confirm the build emitted it
if (!('src/scripts/quantum.js' in manifest.entryModules)) {
  return '/fallback.js';
}
const url = await env.resolve(manifest, 'src/scripts/quantum.js');

Type guard

function hasEntry(
  manifest: { entryModules: Record<string, string> },
  specifier: string,
): specifier is keyof typeof manifest.entryModules & string {
  return specifier in manifest.entryModules;
}

Try / catch

try {
  const url = await env.resolve(manifest, specifier);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unable to resolve [')) {
    return fallbackAssetUrl(specifier);
  }
  throw err;
}

Prevention

When it happens

Trigger: Code or an integration calling `environment.resolve(manifest, specifier)` for an entry that build did not register (conditionally emitted scripts, filtered routes); server bundle and client assets deployed from different builds so the manifest lacks the entry; a typo'd specifier in custom integration code.

Common situations: Partial deploys where `_astro` client assets and the server manifest mismatch; custom renderers/integrations resolving hand-constructed specifiers; asset manifest pruned by post-processing.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/9e06e14415b4f495. Report an issue: GitHub.