[PR #12965] fix: resolve SSE subscription race condition in attach mode #14454

Open
opened 2026-02-16 18:19:14 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/12965

State: open
Merged: No


Summary

Fixes a race condition in the SSE event subscription flow that causes the first message to be silently dropped when using attach mode (opencode attach / opencode run --attach).

Problem

When a client connects to the /event SSE endpoint, three race conditions exist:

1. Server-side: Bus subscription after connect notification

In server.ts, the server.connected event was sent to the client before Bus.subscribeAll() was called. This means:

  • Client receives server.connected → immediately sends a prompt
  • Server processes the prompt → emits bus events
  • But the SSE stream hasn't subscribed to the bus yet → events lost

2. Client-side: TUI usable before SSE ready

In sdk.tsx, the SSE subscription happens in Solid.js onMount() (async), but the TUI prompt is rendered synchronously. Users can type and send a message before the SSE event loop is consuming events.

3. Reconnect gap

On SSE stream reconnection, events between disconnect and re-subscribe are permanently lost (no server-side replay buffer).

Fix

server.ts

Move Bus.subscribeAll() before sending server.connected. This guarantees the bus subscription is active before the client knows it's connected, closing the server-side race window.

sdk.tsx

Add a reactive connected signal that:

  • Starts as false
  • Sets to true when server.connected event is received via SSE
  • Resets to false on reconnection attempts
  • Is exported from the SDK context for consumers to gate message sending

Testing

Reproduction steps:

  1. Start opencode server: opencode serve
  2. Attach from another terminal: opencode attach http://localhost:PORT
  3. Immediately type and send a message
  4. Before fix: First message silently dropped, no response. Second message works.
  5. After fix: First message receives response correctly.

Impact

This affects all attach-mode users, including:

  • First message reliability
  • Background task event delivery
  • Subagent task monitoring
  • Any workflow that sends a prompt shortly after SSE connection
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/12965 **State:** open **Merged:** No --- ## Summary Fixes a race condition in the SSE event subscription flow that causes the **first message to be silently dropped** when using attach mode (`opencode attach` / `opencode run --attach`). ## Problem When a client connects to the `/event` SSE endpoint, three race conditions exist: ### 1. Server-side: Bus subscription after connect notification In `server.ts`, the `server.connected` event was sent to the client **before** `Bus.subscribeAll()` was called. This means: - Client receives `server.connected` → immediately sends a prompt - Server processes the prompt → emits bus events - But the SSE stream hasn't subscribed to the bus yet → **events lost** ### 2. Client-side: TUI usable before SSE ready In `sdk.tsx`, the SSE subscription happens in Solid.js `onMount()` (async), but the TUI prompt is rendered synchronously. Users can type and send a message before the SSE event loop is consuming events. ### 3. Reconnect gap On SSE stream reconnection, events between disconnect and re-subscribe are permanently lost (no server-side replay buffer). ## Fix ### `server.ts` Move `Bus.subscribeAll()` **before** sending `server.connected`. This guarantees the bus subscription is active before the client knows it's connected, closing the server-side race window. ### `sdk.tsx` Add a reactive `connected` signal that: - Starts as `false` - Sets to `true` when `server.connected` event is received via SSE - Resets to `false` on reconnection attempts - Is exported from the SDK context for consumers to gate message sending ## Testing Reproduction steps: 1. Start opencode server: `opencode serve` 2. Attach from another terminal: `opencode attach http://localhost:PORT` 3. Immediately type and send a message 4. **Before fix**: First message silently dropped, no response. Second message works. 5. **After fix**: First message receives response correctly. ## Impact This affects all attach-mode users, including: - First message reliability - Background task event delivery - Subagent task monitoring - Any workflow that sends a prompt shortly after SSE connection
yindo added the pull-request label 2026-02-16 18:19:14 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#14454