fix(client): abort legacy SSE reconnect chain when the originating request times out - #2616
fix(client): abort legacy SSE reconnect chain when the originating request times out#2616claude[bot] wants to merge 17 commits into
Code review found 3 important issues
Found 4 candidates, confirmed 6. See review comments for details.
Details
| Severity | Count |
|---|---|
| 🔴 Important | 3 |
| 🟡 Nit | 3 |
| 🟣 Pre-existing | 0 |
| Severity | File:Line | Issue |
|---|---|---|
| 🔴 Important | packages/core-internal/src/shared/protocol.ts:1421-1428 |
resumptionToken short-circuit: unguarded onerror on request-scoped abort; drops onresumptiontoken/onRequestStreamEnd |
| 🟡 Nit | .changeset/legacy-sse-reconnect-after-timeout.md:1-5 |
Changeset overclaims: wire-visible cancellation IS changed for modern-era maxTotalTimeout settlements |
| 🟡 Nit | docs/migration/support-2026-07-28.md:236-246 |
upgrade-to-v2.md still says requestSignal matters only for 2026-era cancellation — fourth stale doc site |
Annotations
Check failure on line 1428 in packages/core-internal/src/shared/protocol.ts
claude / Claude Code Review
resumptionToken short-circuit: unguarded onerror on request-scoped abort; drops onresumptiontoken/onRequestStreamEnd
On the legacy era this PR newly threads `requestAbort.signal` into the transport's resumptionToken short-circuit (`_send` in `packages/client/src/client/streamableHttp.ts`, ~line 957), but that path's outer `.catch(error => this.onerror?.(error))` has no intentional-abort guard — so a timeout/abort landing while the resume GET is in flight surfaces a spurious `AbortError` through `client.onerror`, contradicting the "no spurious onerror" contract this diff's comments and docs state. A one-line gu
Check warning on line 5 in .changeset/legacy-sse-reconnect-after-timeout.md
claude / Claude Code Review
Changeset overclaims: wire-visible cancellation IS changed for modern-era maxTotalTimeout settlements
The changeset's claim that "the wire-visible cancellation behavior is unchanged for every (era × transport) combination" overclaims: the new `.finally()` `requestAbort?.abort()` makes modern-era (2026-07-28) `maxTotalTimeout` settlements close the per-request stream — which on that era IS the spec cancellation signal — where pre-PR nothing was put on the wire on that path (and successful completions now actively close the stream too). The behavior change is desirable, but the sentence should be
Check warning on line 246 in docs/migration/support-2026-07-28.md
claude / Claude Code Review
upgrade-to-v2.md still says requestSignal matters only for 2026-era cancellation — fourth stale doc site
The doc-update round in 29c4e86 fixed three of the four prose sites describing the old 2026-only `requestSignal` contract, but a fourth survives: the "Transport interface contract" bullet in `docs/migration/upgrade-to-v2.md` (~lines 1823-1832) still says `hasPerRequestStream` / `requestSignal` / `onRequestStreamEnd` "matter only for 2026-era per-request-stream cancellation and Mcp-Param-* header attachment" — after this PR the signal is threaded and aborted on every settlement at either era. Sam