Which @angular/* package(s) are the source of the bug?
@angular/ssr
Is this a regression?
No
Description
When multiple parameterized routes use RenderMode.Prerender with getPrerenderParams, some routes are silently skipped — getPrerenderParams is never called, no prerendered HTML is produced, and no warning is emitted. The build reports "Prerendered N static routes" with N lower than expected.
Root cause
In @angular/ssr/fesm2022/ssr.mjs, function handleSSGRoute:
const URL_PARAMETER_REGEXP = /(?<!\\):([^/]+)/g; // <-- /g flag
if (isCatchAllRoute && !getPrerenderParams ||
!isCatchAllRoute && !URL_PARAMETER_REGEXP.test(currentRoutePath)) {
yield { ...meta }; // early return, getPrerenderParams never called
return;
}
The /g flag makes RegExp.prototype.test() stateful — lastIndex persists across calls. After a successful match, the next .test() call starts mid-string and may return false for a path that does contain a parameter. The route is then treated as static and yielded without invoking getPrerenderParams.
Standalone reproduction (no Angular needed)
const URL_PARAMETER_REGEXP = /(?<!\\):([^/]+)/g;
console.log(URL_PARAMETER_REGEXP.test('blog/:slug')); // true
console.log(URL_PARAMETER_REGEXP.test('blog/kategorie/:cat')); // false ← BUG
Suggested fix
Drop the /g flag (not needed for .test()), or reset lastIndex before each test:
const isCatchAllRoute = CATCH_ALL_REGEXP.test(currentRoutePath);
+ URL_PARAMETER_REGEXP.lastIndex = 0;
if (isCatchAllRoute && !getPrerenderParams || !isCatchAllRoute && !URL_PARAMETER_REGEXP.test(currentRoutePath)) {
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No exception. The bug is silent: getPrerenderParams is not invoked for affected routes, and the build log reports a lower count of prerendered routes than expected without any warning.
Please provide the environment you discovered this bug in (run ng version)
Angular : 21.2.4
Node.js : 22.14.0
Package Manager : pnpm 10.6.5
Operating System : win32 x64
Package Installed Version Requested Version
@angular/build 21.2.2 ^21.2.2
@angular/cdk 21.2.2 ^21.2.2
@angular/cli 21.2.2 ^21.2.2
@angular/common 21.2.4 ^21.2.0
@angular/compiler 21.2.4 ^21.2.0
@angular/compiler-cli 21.2.4 ^21.2.0
@angular/core 21.2.4 ^21.2.0
@angular/forms 21.2.4 ^21.2.0
@angular/material 21.2.2 ^21.2.2
@angular/platform-browser 21.2.4 ^21.2.0
@angular/platform-server 21.2.4 ^21.2.0
@angular/router 21.2.4 ^21.2.0
@angular/ssr 21.2.2 ^21.2.2
rxjs 7.8.2 ~7.8.0
typescript 5.9.3 ~5.9.2
Anything else?
Also reproduced with @angular/ssr 21.2.10 and 22.0.0-next.7 by patching the file in node_modules and rerunning the build — the same routes are skipped without the lastIndex = 0 fix.
Currently working around this via pnpm patch:
const isCatchAllRoute = CATCH_ALL_REGEXP.test(currentRoutePath);
+ URL_PARAMETER_REGEXP.lastIndex = 0;
if (isCatchAllRoute && !getPrerenderParams || !isCatchAllRoute && !URL_PARAMETER_REGEXP.test(currentRoutePath)) {
Before patch: 7 of 11 expected parameterized routes were prerendered.
After patch: all 20 routes correctly prerendered.
Happy to submit a PR if helpful.
Which @angular/* package(s) are the source of the bug?
@angular/ssr
Is this a regression?
No
Description
When multiple parameterized routes use
RenderMode.PrerenderwithgetPrerenderParams, some routes are silently skipped —getPrerenderParamsis never called, no prerendered HTML is produced, and no warning is emitted. The build reports "Prerendered N static routes" with N lower than expected.Root cause
In
@angular/ssr/fesm2022/ssr.mjs, functionhandleSSGRoute:The
/gflag makesRegExp.prototype.test()stateful —lastIndexpersists across calls. After a successful match, the next.test()call starts mid-string and may returnfalsefor a path that does contain a parameter. The route is then treated as static and yielded without invokinggetPrerenderParams.Standalone reproduction (no Angular needed)
Suggested fix
Drop the
/gflag (not needed for.test()), or resetlastIndexbefore each test:const isCatchAllRoute = CATCH_ALL_REGEXP.test(currentRoutePath); + URL_PARAMETER_REGEXP.lastIndex = 0; if (isCatchAllRoute && !getPrerenderParams || !isCatchAllRoute && !URL_PARAMETER_REGEXP.test(currentRoutePath)) {Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
Please provide the environment you discovered this bug in (run
ng version)Anything else?
Also reproduced with
@angular/ssr21.2.10 and 22.0.0-next.7 by patching the file innode_modulesand rerunning the build — the same routes are skipped without thelastIndex = 0fix.Currently working around this via
pnpm patch:const isCatchAllRoute = CATCH_ALL_REGEXP.test(currentRoutePath); + URL_PARAMETER_REGEXP.lastIndex = 0; if (isCatchAllRoute && !getPrerenderParams || !isCatchAllRoute && !URL_PARAMETER_REGEXP.test(currentRoutePath)) {Before patch: 7 of 11 expected parameterized routes were prerendered.
After patch: all 20 routes correctly prerendered.
Happy to submit a PR if helpful.