You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SSE handlers register onAbort after the priming write, so a disconnect during that await leaks the consumer/watcher and hangs the handler #1999
Found by Copilot reviewing the v2.2.0 milestone merge (#1993), verified against the installed hono.
#1946 added a priming write so Firefox's fetch() resolves on an SSE stream that may never emit. In both SSE handlers in core/mcp/remote/node/server.ts that write is awaited beforestream.onAbort(...) is registered:
~core/mcp/remote/node/server.ts:851-862 — the session event stream (setEventConsumer already installed)
Hono's StreamingApi.onAbort is a plain push with no already-aborted replay (node_modules/hono/dist/utils/stream.js:65-66), and abort() fires only the subscribers registered at that moment (:73-76). So if the client disconnects while the priming write is in flight, every onAbort handler registered afterwards never runs:
the event consumer / serverEventSubscribers entry is never cleared, and maybeStopWatcher() never runs — the mcp.json watcher stays alive with a dead subscriber, and later writes go to a closed stream;
the session is never deleted from sessions;
the terminal await new Promise(resolve => stream.onAbort(resolve)) never resolves — the handler is parked forever.
The window is narrow (a disconnect inside a single small write) but it is a real leak, and it did not exist before the priming write introduced an await at that point.
Constraint
The ordering is not accidental and must be preserved: :2427-2432 documents that the subscriber and watcher are installed before priming on purpose, because callers treat the stream's first bytes as proof they are subscribed. The fix is to move the cleanup registration earlier, not the priming.
Suggested shape
Register one abort promise that performs the cleanup before the first await, then await it after priming — e.g.
Severity 3 — a real resource leak (subscriber + file watcher + a parked handler), but behind a narrow disconnect race, and the Inspector is a dev tool with short-lived sessions
Urgency 2 — wanted eventually; nothing is blocked on it
I traced the race described here to the window where a priming write is still pending when the client aborts, before abort cleanup has been registered. Cleanup can therefore be missed on both the session-event stream and the server-list change stream. I can implement a single idempotent abort/cleanup path and add deterministic regression coverage for disconnect during the pending write, including session/handler completion and subscriber/watcher teardown. I understand that this repository asks external contributors to provide an implementation prompt rather than open a PR directly. Would a maintainer be willing to invite me to implement this, grant the appropriate contribution access, or open a PR from an external branch? If not, I am happy to leave only the detailed implementation prompt and test plan here.
Activity
cliffhall commentedon Aug 12, 2026
Triage: Priority Medium (total 6)
buglabelBoard: #28, Status
Todo, milestone v2.3.0.KirschBluteX commentedon Aug 14, 2026
I traced the race described here to the window where a priming write is still pending when the client aborts, before abort cleanup has been registered. Cleanup can therefore be missed on both the session-event stream and the server-list change stream. I can implement a single idempotent abort/cleanup path and add deterministic regression coverage for disconnect during the pending write, including session/handler completion and subscriber/watcher teardown. I understand that this repository asks external contributors to provide an implementation prompt rather than open a PR directly. Would a maintainer be willing to invite me to implement this, grant the appropriate contribution access, or open a PR from an external branch? If not, I am happy to leave only the detailed implementation prompt and test plan here.
cliffhall commentedon Aug 17, 2026
Fixed by #2045 (merged to
v2/mainas 8852286).fix: register SSE abort cleanup before the priming write