angular/angular-cli · error · Error
'handleSSGRoute' was called for a route which rendering mode
Error message
'handleSSGRoute' was called for a route which rendering mode is not prerender.
What it means
This error is thrown by the Angular SSR route-tree builder when `handleSSGRoute` is invoked for a route whose `renderMode` is not `RenderMode.Prerender`. It is an internal invariant check: only prerender-mode route metadata should ever reach the SSG handling path. Hitting it means the route tree construction logic dispatched a non-prerender route (e.g. Server or Client render mode) into the static-generation handler.
Source
Thrown at packages/angular/ssr/src/routes/ng-routes.ts:410
*
* @param serverConfigRouteTree - The tree representing the server's routing setup.
* @param redirectTo - Optional path to redirect to, if specified.
* @param metadata - The metadata associated with the route tree node.
* @param parentInjector - The dependency injection container for the parent route.
* @param invokeGetPrerenderParams - A flag indicating whether to invoke the `getPrerenderParams` function.
* @param includePrerenderFallbackRoutes - A flag indicating whether to include fallback routes in the result.
* @returns An async iterable iterator that yields route tree node metadata for each SSG path or errors.
*/
async function* handleSSGRoute(
serverConfigRouteTree: RouteTree<ServerConfigRouteTreeAdditionalMetadata> | undefined,
redirectTo: string | undefined,
metadata: ServerConfigRouteTreeNodeMetadata,
parentInjector: Injector,
invokeGetPrerenderParams: boolean,
includePrerenderFallbackRoutes: boolean,
): AsyncIterableIterator<RouteTreeNodeMetadata | { error: string }> {
if (metadata.renderMode !== RenderMode.Prerender) {
throw new Error(
`'handleSSGRoute' was called for a route which rendering mode is not prerender.`,
);
}
const { route: currentRoutePath, fallback, ...meta } = metadata;
const getPrerenderParams = 'getPrerenderParams' in meta ? meta.getPrerenderParams : undefined;
if ('getPrerenderParams' in meta) {
delete meta['getPrerenderParams'];
}
if (redirectTo !== undefined) {
meta.redirectTo = resolveRedirectTo(currentRoutePath, redirectTo);
}
const isCatchAllRoute = CATCH_ALL_REGEXP.test(currentRoutePath);
if (
(isCatchAllRoute && !getPrerenderParams) ||View on GitHub (pinned to bb72145f9a)
Solutions
- Inspect `app.routes.server.ts` and ensure every route fed into SSG/prerender handling declares `renderMode: RenderMode.Prerender`.
- Set the intended mode explicitly, e.g. `{ '/**': { renderMode: RenderMode.Server } }` for dynamic routes instead of relying on defaults.
- Remove any custom code that calls `handleSSGRoute` (or route-tree internals) directly with non-prerender metadata.
- Update @angular/ssr and @angular/core to matching latest patch versions and rebuild; if reproducible on clean config, file a bug with a minimal repo.
Example fix
// before (server routes)
const serverRoutes: ServerRoute[] = [
{ path: 'products/:id', renderMode: RenderMode.Server },
];
// after
const serverRoutes: ServerRoute[] = [
{ path: 'products/:id', renderMode: RenderMode.Prerender, getPrerenderParams: async ({ params }) => [/* ids */] },
]; Defensive patterns
Strategy: validation
Validate before calling
import { RenderMode } from '@angular/ssr';
const isPrerender = (m: { renderMode?: RenderMode }) => m.renderMode === RenderMode.Prerender;
if (!serverRoutes.every(r => !needsSsg(r.path) || isPrerender(r))) {
throw new Error('SSG routes must declare renderMode: RenderMode.Prerender');
} Type guard
function isPrerenderMetadata(m: ServerConfigRouteTreeNodeMetadata): boolean {
return m.renderMode === RenderMode.Prerender;
} Try / catch
try {
for await (const meta of handleSSGRoute(route, metadata, injector, true, true)) { /* ... */ }
} catch (e) {
if (String(e?.message).includes("'handleSSGRoute' was called")) {
console.error('Route is not prerender-mode:', metadata.route, metadata.renderMode);
} else throw e;
} Prevention
- Explicitly declare `renderMode` on every entry in `app.routes.server.ts`; never rely on defaults.
- Keep @angular/core and @angular/ssr versions exactly in sync.
- Do not call internal route-tree APIs (`handleSSGRoute`) from application code.
- Run a prerender build in CI to surface mode mismatches early.
When it happens
Trigger: A route's ServerRoute metadata has renderMode set to Server/Client but is passed to `handleSSGRoute` during route extraction; typically caused by mismatched route configuration or an internal dispatch bug in `handleRoute`.
Common situations: Mixing `RenderMode.Server` or `RenderMode.Client` routes with prerender expectations in `app.routes.server.ts`; upgrading @angular/ssr where route metadata shapes changed; custom route-tree tooling calling internal APIs directly.
Related errors
- The 'getPrerenderParams' function defined for the '${stripLe
- Could not find any routes to prerender.
- The builder requires a target.
- Rendering failed with ${numErrors} worker errors.
- A module or bootstrap option must be provided.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/7382ddb47e80b5b5.
Report an issue: GitHub.