#18538 · @zaxbysauce · opened Mar 21, 2026 at 4:37 PM UTC · last updated Mar 21, 2026 at 4:38 PM UTC
fix(opencode): handle client disconnect in SSE event route writes
Score breakdown
Impact
Clarity
Urgency
Ease Of Review
Guidelines
Readiness
Size
Trust
Traction
Summary
This PR fixes a critical server stability bug where client disconnects or rapid bus events cause unhandled errors in SSE event routes. The issue leads to server corruption,
Description
Issue for this PR
Closes #15149
Type of change
- [x] Bug fix
- [ ] New feature
- [ ] Refactor / code improvement
- [ ] Documentation
What does this PR do?
The /event and /global/event SSE endpoints use an AsyncQueue drained by a for await loop that calls stream.writeSSE(). When a client disconnects abruptly — or when rapid-fire bus events cause writeSSE backpressure — the thrown error propagates out of the for await loop unhandled. This corrupts server state, causing subsequent requests to fail with "Unexpected EOF" errors and killing active sessions.
This is the same bug as the original PR #15147, rebased onto the current dev branch where the SSE routes were refactored from inline server.ts handlers into separate routes/event.ts and routes/global.ts files using the AsyncQueue pattern.
The fix wraps each writeSSE call inside the for await drain loop in a try/catch. On failure, it logs the disconnection and returns cleanly, letting the finally block run stop() to clear the heartbeat interval and unsubscribe from the bus. Two files changed, identical pattern in both.
How did you verify your code works?
- Traced the crash path from
bash.ts(fire-and-forgetctx.metadata()on every stdout chunk) throughSession.updatePart()→Bus.publish(PartUpdated)→AsyncQueue.push()→stream.writeSSE()failure → unhandled throw → session death - Reproduced the crash by running a test suite that produces 40+ rapid bus events through the MCP bash tool, overwhelming the SSE drain loop
- Confirmed the fix pattern matches the existing try/catch handling already used in the
server.tsinline SSE handler from the original PR
Screenshots / recordings
Not a UI change.
Checklist
- [x] I have tested my changes locally
- [x] I have not included unrelated changes in this PR
If you do not follow this template your PR will be automatically rejected.
Linked Issues
#15149 Server becomes unresponsive after external client disconnects during SSE streaming
View issueComments
No comments.
Changed Files
packages/opencode/src/server/routes/event.ts
+6−1packages/opencode/src/server/routes/global.ts
+6−1