Skip to content

Bug: prompt_async stops publishing message.part.delta events on second call (conversation continuation) #27663

@webster-yuan

Description

@webster-yuan

Bug Description

When prompt_async is called a second time on the same session (conversation continuation / resume), message.part.delta events stop being published entirely. Only initial state sync events (message.updated, message.part.updated, session.updated) arrive, followed by nothing but heartbeats.

Steps to Reproduce

  1. Create a session and send the first prompt_async — observe message.part.delta events flowing normally on both /event and /global/event
  2. After the first prompt completes (session idle), send a second prompt_async on the same session
  3. Observe the SSE stream: only message.updated / message.part.updated / session.updated arrive, then only server.heartbeat — no message.part.delta ever

Environment

  • opencode version: v1.14.50
  • SSE endpoint tested: both /event (instance-level) and /global/event
  • Same behavior on both endpoints

What We have Ruled Out

  1. Not an SSE subscription layer issue: We switched to /global/event (which uses GlobalBus — simple EventEmitter, no Effect fibers). Same problem persists. This means Bus.publish() is never called for deltas during the second prompt.
  2. Not a content complexity issue: A simple task that completes in one turn works fine. A complex task that triggers multi-turn interaction (planning → questions → file writes) triggers the bug.
  3. Root cause is in the prompt execution pipeline, not in SSE/bus subscription — Bus.publish() itself calls both PubSub.publish() and GlobalBus.emit() (confirmed in bus/index.ts:87-108), so the event is simply never created for the second prompt.

Suspected Root Cause

The second prompt_async call on an existing session seems to execute the prompt in a different code path or Effect scope where updatePartDelta() / Bus.publish() is either skipped or uses a different bus instance.

Relevant code paths:

  • handlers/session.ts:270-286promptAsync uses Effect.forkIn(scope)
  • session/message-v2.tsupdatePartDelta() publishes deltas via Bus.publish()
  • bus/index.ts:87-108publish() calls both PubSub and GlobalBus

Real-World Impact

This breaks any conversation-continuation flow — when a user answers a question or confirms a permission, the subsequent agent work becomes invisible to SSE clients. Frontends relying on SSE for real-time streaming see the agent "stuck" with no progress updates after the first interaction.

Note

PR #26678 (switching /event from Bus.Service to GlobalBus) addresses a related but different issue — it fixes the SSE subscription closing prematurely. Even with that fix applied (by using /global/event directly), this second-prompt delta bug remains.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions