AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

After() Retains Request Async Context For Never-Settling Promises Causing Memory Leak

When after() is called with a promise that never settles, the bookkeeping .then() callback registers in the caller's async context, pinning the entire request-scoped context (including RSC payloads) for the lifetime of the server process, leading to unbounded memory growth.

highConfidence 95%Next.jsAffected V16.2.12Affected V16.3.4Affected V16.4.0-Canary.26

Origin Analysis

In packages/next/src/server/after/awaiter.ts, AwaiterMulti.waitUntil attaches a .then() reaction to the given promise. This reaction is registered within the caller's AsyncLocalStorage context, so the promise's pending state holds a reference to that context. If the promise never settles, the context (and everything reachable from it, such as the request work-unit store and flight data) is retained indefinitely. On self-hosted servers the awaiter lives for the process lifetime, so the leak accumulates with each request that passes a never-settling promise.
1. Clone reproduction repo: https://github.com/mircoservices/next-after-waituntil-context-leak 2. npm install && npm run build 3. npm start (sets NODE_OPTIONS=--expose-gc) 4. In another shell run: node measure.mjs settled 300, node measure.mjs detached 300, node measure.mjs leak 300 5. Observe /api/heap reports arrayBuffers retained: settled=0, detached=0, leak=300 MiB (1 MiB per request).

Fixing Code Block

Edge Case Audit

This change moves onError execution out of the caller's async context, which may affect error logging or tracing that relies on request context for rejected tasks. It also does not prevent the Set from growing if many never-settling promises are added, though memory retention from the context is eliminated. Rollback: if error handling regressions appear, revert to the original waitUntil and consider alternative bounding strategies (e.g., timeout-based cleanup). Extra care needed in environments without AsyncLocalStorage snapshot support; the fallback keeps old behavior.

Ecosystem Topology