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

  1. Inspect `app.routes.server.ts` and ensure every route fed into SSG/prerender handling declares `renderMode: RenderMode.Prerender`.
  2. Set the intended mode explicitly, e.g. `{ '/**': { renderMode: RenderMode.Server } }` for dynamic routes instead of relying on defaults.
  3. Remove any custom code that calls `handleSSGRoute` (or route-tree internals) directly with non-prerender metadata.
  4. 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

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


AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30). Data as JSON: /api/errors/7382ddb47e80b5b5. Report an issue: GitHub.