withastro/astro · error · Error
Couldn't find component for route
Error message
Couldn't find component for route ${routeData.pathname} What it means
The experimental Astro container renders through a per-container WeakMap (the `interner`) mapping RouteData to its page module. Only routes created by that container's own renderToResponse/insertRoute flow — plus rewrites resolved against the same manifest — are interned. This error means getComponentByRoute was handed a RouteData that this container instance never registered.
Solutions
- Render via the container's public API — `container.renderToString(Component, { request })` / `container.renderToResponse(Component, { params, request })` — so the container creates and interns its own RouteData
- For rewrites in container tests, ensure the rewrite target route is one this container rendered/inserted; avoid rewriting to non-inserted routes
- Never share RouteData between container instances: each container has its own interner, so create and use the RouteData within the same instance
Example fix
// before: reusing a RouteData this container never interned
const routeData = savedRouteDataFromAnotherContainer;
await renderWithRoute(container, routeData, request);
// after: let the container create + intern its own route
const container = await experimental_AstroContainer.create();
const html = await container.renderToString(Page, {
request: new Request('https://example.com/page'),
}); Defensive patterns
Strategy: try-catch
Try / catch
try {
const html = await container.renderToString(Page, { request });
} catch (e) {
if (e instanceof Error && e.message.startsWith("Couldn't find component for route")) {
// the RouteData was never interned by THIS container:
// re-render via renderToString/renderToResponse so the container owns the route
} else {
throw e;
}
} Prevention
- Always render through `container.renderToString`/`renderToResponse` instead of hand-built RouteData
- Create one container per test case and never share RouteData or component instances across containers — the interner is a per-instance WeakMap
- In container tests, avoid `Astro.rewrite` to paths the container has not rendered/inserted
When it happens
Trigger: Rendering with a RouteData obtained from another `experimental_AstroContainer` instance, from a real app's SSR manifest, or built by hand; an `Astro.rewrite()` inside a container test targeting a route that was never inserted into this container; caching RouteData across container instances.
Common situations: Unit-test harnesses that construct RouteData manually or reuse saved route objects; middleware that rewrites to a path with no corresponding inserted route; mixing manifest-based routes into container-based rendering.
Related errors
- The renderer name must be provided when adding a server…
- The renderer you passed isn't valid. A renderer is usually…
- You tried to add the
- A collision will result in a hard error in following…
- Could not find server component name
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/1bbf21f1d47f7f18.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/container/environment.ts:89
* The container environment. Registered by `experimental_AstroContainer`'s
* constructor on its fabricated manifest — the container never touches the
* ambient manifest, so multiple containers in one process stay isolated.
*/
export function createContainerEnvironment({
interner,
resolve,
renderers,
streaming,
}: ContainerEnvironmentOptions): RenderEnvironment {
async function getComponentByRoute(
_manifest: SSRManifest,
routeData: RouteData,
): Promise<ComponentInstance> {
const page = interner.get(routeData);
if (page) {
return page.page();
}
throw new Error("Couldn't find component for route " + routeData.pathname);
}
return {
name: 'container',
runtimeMode: 'development',
defaultStreaming: () => streaming,
async resolve(_manifest: SSRManifest, specifier: string): Promise<string> {
return resolve(specifier);
},
headElements(manifest: SSRManifest, routeData: RouteData): HeadElements {
const routeInfo = manifest.routes.find((route) => route.routeData === routeData);
const links = new Set<never>();
const scripts = new Set<SSRElement>();
const styles = createStylesheetElementSet(routeInfo?.styles ?? []);
for (const script of routeInfo?.scripts ?? []) {View on GitHub (pinned to 52e6c34790)