Repository navigation
beforeAuthStateChanged imported from @angular/fire/auth makes ng build fail during route extraction #3748
Description
Description
@angular/fire/auth wraps beforeAuthStateChanged as ɵzoneWrap(_beforeAuthStateChanged, true) (src/auth/firebase.ts line 61). With that flag, the wrapper registers a pending task as soon as a callback is passed and clears it only when the callback first fires or the returned unsubscribe runs (src/zones.ts). This callback only fires when a sign-in or sign-out happens, so an app that registers the hook at startup holds the pending task open and ApplicationRef.isStable never becomes true for a visitor who is not signing in or out.
ng build route extraction waits on app stability, so any server-rendered app that registers this hook in its app config cannot build. Extraction hangs for about 30 seconds, then:
AbortError: Routes extraction was aborted.
TimeoutError: The operation was aborted due to timeout
Steps to reproduce
- Fresh
ng new --ssrAngular 21 app,ng add @angular/fire@next. - In
app.config.ts, registerbeforeAuthStateChangedinsideprovideAppInitializer, imported from@angular/fire/auth. Registering it at startup is exactly what an SSR token-cookie sync does (docs/auth.md, Server-side Rendering section). ng buildfails with the error above (34 seconds in my run).- Change only the import to
firebase/auth. The identical code builds in under 5 seconds.
Expected behavior
Registering the hook does not permanently block app stability. onMessage in src/messaging/firebase.ts wraps the same shape of API, a callback that may never fire, with the flag set to false, which still zone-wraps the callback and only skips the pending task. The same flag here looks like the fix, pending a check that nothing relies on the blocking behavior. onLog in src/app/firebase.ts has the same shape and is worth sweeping at the same time.
Workarounds in the wild
Our own sample already imports beforeAuthStateChanged from firebase/auth (sample/src/app/auth/auth.component.ts), and the rewritten SSR docs section in #3740 documents that import as the way around this bug.
Versions
Reproduced on an Angular 21 app against the @angular/fire 21 canary. The wrapper is unchanged on current main.
Activity
docs(auth): restructure step 2 cookie guidance per review
docs(auth): rewrite the server-side rendering section (#3740)
armando-navarro commentedon Sep 25, 2026
A correction and an addition to the report above, after reproducing it again on
21.0.0-rc.1.Correction to step 2
Step 2 says registering the hook at startup is exactly what the cookie sync in
docs/auth.mddoes. That isn't quite right. The guide's code returns early when it isn't running in the browser, so it registers the hook only in the browser, andng buildsucceeds with the hook imported from@angular/fire/auth. The build failure needs the hook registered on the server as well.Where it shows up
ng build, with the hook registered on the server: route extraction times out, as described above.RenderMode.Server): a request gets no response at all. None arrived within 60 seconds.ApplicationRef.whenStable()does not resolve until someone signs in or out.docs(auth): scope the beforeAuthStateChanged note to rc.1 and earlier
fix(auth): stop beforeAuthStateChanged from holding the app unstable (a…
fix(auth): stop beforeAuthStateChanged from holding the app unstable (a…
fix(auth): stop beforeAuthStateChanged from holding the app unstable (#…