Skip to content

@angular/ssr: an aborted request rejects handle() but the render keeps running #34567

Closed

Description

@denisyilmaz

Which @angular/* package(s) are the source of the bug?

platform-server

Is this a regression?

No

Description

AngularServerApp.handle() wraps handleRendering() in promiseWithAbort(…, request.signal, …) (packages/angular/ssr/src/app.ts). When the signal aborts, the returned promise rejects, but nothing stops the render: the platform renderAngular() created stays alive, its HTTP calls keep going, and the app goes on rendering a page nobody will receive.

This makes request.signal unusable as a render timeout. A server that caps renders (to answer 503 before the proxy's own timeout, and to limit how many renders run at once) gets its promise back on time while the work piles up in the background. With a slow backend, every abandoned render is still running when the next batch starts.

Reproduction: a route whose component issues an HttpClient GET to a backend that answers after 60 s. Call engine.handle(new Request(url, { signal: AbortSignal.timeout(5_000) })). handle() rejects at 5 s; the backend still sees the request run to completion, and any request the app makes after that response still arrives. On our app (22.2.2), three renders aborted at 50 s made 8 more backend calls once the backend answered.

Suggested fix

Pass the signal into renderAngular() and destroy the platform on abort, the same way it is destroyed after a normal render:

// utils/ng.ts, inside renderAngular(), after platformServer(...)
const onAbort = () => void asyncDestroyPlatform(platformRef);
signal?.addEventListener('abort', onAbort, { once: true });
// ...and remove the listener in the existing finally / destroy paths

The rest already works: destroying the app clears PendingTasks, so whenStable() settles; the applicationRef.destroyed check added in 730ae66 ("handle platform destruction during rendering") returns { hasNavigationError: true }; and FetchBackend aborts its fetch when the destroyed app's subscriptions are torn down.

Workaround (what we ship now), in app.config.server.ts:

provideEnvironmentInitializer(() => {
  const signal = inject(REQUEST, { optional: true })?.signal;
  if (!signal) return;
  const platform = inject(PlatformRef);
  const destroy = () => setTimeout(() => platform.destroyed || platform.destroy());
  if (signal.aborted) return destroy();
  signal.addEventListener('abort', destroy, { once: true });
  inject(DestroyRef).onDestroy(() => signal.removeEventListener('abort', destroy));
});

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)

Angular CLI       : 22.2.2
Angular           : 22.2.2
Node.js           : 24.22.1
Package Manager   : npm 11.19.1
Operating System  : darwin arm64

┌───────────────────────────────────┬───────────────────┬───────────────────┐
│ Package                           │ Installed Version │ Requested Version │
├───────────────────────────────────┼───────────────────┼───────────────────┤
│ @angular/aria                     │ 22.2.2            │ ^22.2.2           │
│ @angular/build                    │ 22.2.2            │ ^22.2.2           │
│ @angular/cdk                      │ 22.2.2            │ ^22.2.2           │
│ @angular/cli                      │ 22.2.2            │ ^22.2.2           │
│ @angular/common                   │ 22.2.2            │ ^22.2.2           │
│ @angular/compiler                 │ 22.2.2            │ ^22.2.2           │
│ @angular/compiler-cli             │ 22.2.2            │ ^22.2.2           │
│ @angular/core                     │ 22.2.2            │ ^22.2.2           │
│ @angular/elements                 │ 22.2.2            │ ^22.2.2           │
│ @angular/forms                    │ 22.2.2            │ ^22.2.2           │
│ @angular/platform-browser         │ 22.2.2            │ ^22.2.2           │
│ @angular/platform-browser-dynamic │ 22.2.2            │ ^22.2.2           │
│ @angular/platform-server          │ 22.2.2            │ ^22.2.2           │
│ @angular/router                   │ 22.2.2            │ ^22.2.2           │
│ @angular/ssr                      │ 22.2.2            │ ^22.2.2           │
│ ng-packagr                        │ 22.1.1            │ ^22.1.1           │
│ rxjs                              │ 7.8.2             │ ~7.8.2            │
│ typescript                        │ 6.0.3             │ ~6.0.3            │
│ vitest                            │ 4.1.9             │ ^4.1.9            │
└───────────────────────────────────┴───────────────────┴───────────────────┘

Anything else?

No response

Activity

  1. added this to the needsTriage milestone on Oct 28, 2026
  2. added this to the needsTriage milestone on Oct 28, 2026
  3. transferred this issue fromangular/angularon Oct 28, 2026
  4. added a commit that references this issue on Oct 28, 2026
    322f09f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions