fix(replay): stop a failed network body read from breaking the host fetch - #4711
Conversation
…etch On Safari, canceling a reader whose underlying transfer already died rejects with `TypeError: Load failed`. `_tryReadBodyStreaming` discarded that promise with `void reader?.cancel()`, so the rejection escaped as an uncaught error and broke the function's never-reject contract. Attach a no-op rejection handler to the cancel() promise, and guard the response body read in the fetch patch so a body-read failure can never propagate into a request the page already got a good response for. Generated-By: PostHog Desktop Task-Id: 327ac857-0f25-45f1-867d-b3c6f1297a7e
Replay incident risk checkThis diff touches code involved in past incidents. This is a heads-up, not a verdict: read the matched sections of INCIDENTS.md and answer their review questions before merging. For a judgment on whether this diff has the same failure mode, run the |
posthog-js Compliance ReportDate: 2026-09-01 17:37:31 UTC ✅ All Tests Passed!26/26 tests passed Capture Tests✅ 26/26 tests passed View Details
|
|
Size Change: +855 B (0%) Total Size: 20.8 MB 📦 View Changed
ℹ️ View Unchanged
|
Replay incident risk — review questions answeredThe bot matched Class 1 (version skew) and Class 3 (network primitive wrappers). The diff adds only defensive error handling; it does not change request construction, body forwarding, any persisted state, or any cross-boundary signature. Class 1 — version skew across the lazy-load boundary
Class 3 — network primitive wrappers
Standing-policy flag for a human reviewerClass 3 records a standing policy: no AI-generated PRs in the wrappers. This PR is AI-generated and edits |
…-body-read-a8b381

Problem
TypeError: Load failedfrom the replay network capture plugin — a failed response body read escaping into the page's ownfetch()call._tryReadBodyStreamingpromises it is guaranteed to resolve, never reject. Every read path honors that except one:void reader?.cancel()discarded the promisecancel()returns, and the surroundingtry/catchcannot catch an async rejection. On Safari, canceling a reader whose transfer already died rejects withTypeError: Load failed— the exact type, message, and browser observed.catch, so a body-read failure could reject the patchedfetchand break a request the page had already received a good response for. Commitf07e241bexists specifically so network capture never breaks the host page; this path defeated that.streamNetworkBody— but the failure class is the reason to fix it.Changes
cancel()promise, so a reader that rejects on cancel can never escape the never-reject helper.fetch._tryReadBodyStreamingresolves normally and raises no unhandled rejection whencancel()rejects with the Safari error.Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Fully autonomous
void reader?.cancel()line; I confirmeddone()callscancel()on every settle (including success), so the rejected promise floats regardless of read outcome. I verified the regression test fails without the fix (unhandledTypeError) and passes with it.try/catchthat swallows and logs, so it needed no change.Created with PostHog Desktop from this inbox report.