Skip to content

SSE /api/event fibers interrupted mid-turn by provider/model config reload triggered from other connected directories (v2.0.26, Windows) #54282

Closed as not planned

Description

@CheneyDu0129

Draft — GitHub issue for anomalyco/opencode

Title: SSE /api/event fibers interrupted mid-turn by provider/model config reload triggered from other connected directories (v2.0.26, Windows)


Environment

  • opencode: v2.0.26 (@opencode/cli via npm global, Bun runtime) on Windows 11
  • Architecture: one shared background server on a fixed port, serving multiple clients via ?directory= workspaces (6 distinct directories connected concurrently)
  • Providers: default + one custom OpenAI-compatible provider with a 16-model whitelist (relevant because config reloads are frequent)

Summary

When provider/model configuration is reloaded on the shared server — apparently triggered by clients connecting from other directories — in-flight SSE streams on /api/event for unrelated, active sessions are torn down with InterruptError: All fibers interrupted without error. The HTTP response itself completes with status 200, but the event stream simply stops mid-turn. CLI clients running opencode run --format json then exit silently (no terminal event), which downstream tools interpret as a crash and retry.

Observed behavior (2026-10-10, all times UTC)

Server log (~/.local/share/opencode/log/opencode.log) shows bursts of:

timestamp=2026-10-10T07:00:16.095Z level=INFO run=bf476822 cause="InterruptError: All fibers interrupted without error\n at ServerProcess.start (B:/~BUN/root/chunk-gn3byahv.js:2:7477)..." http.span=15810 http.method=GET http.url=/api/event http.status=200
  • 22 such interrupts between 06:4x and 07:0x on one hour alone.
  • Each affected GET /api/event has a large http.span (e.g. 15810 ms) and still returns http.status=200 — the interruption happens while the SSE response is streaming.
  • The server process does not restart (stable PID across the whole window, 19 active connections) — this is not a watchdog/service-replacement issue.

Correlation on the client side (a desktop tool spawning opencode run --format json --session <id> per task):

cli starting ... args=["run","--format","json","--dangerously-skip-permissions","--model","...","--session","ses_edb74a31dffedlcMIDfbjAJjWZ"]

followed by no further output (silent death). The same session was resumed 16 times between 06:41 and 07:00 — each resume starting a fresh CLI that again hit an interrupted stream — burning tokens each time.

The server log in the same period is dominated by config-churn events (provider:updated etc., on the order of 1300+ events/day across the connected directories), consistent with ScopedCache invalidation racing in-flight request fibers.

Impact

  • Any multi-client setup where one workspace's config reload can kill unrelated active streams.
  • Silent CLI exit gives callers no usable error to distinguish "stream interrupted" from "model/provider failure", causing retry storms in wrapping tools.

Suspected mechanism

Same class as #32755 (ScopedCache invalidation → instance disposal interrupts all in-flight lookup fibers): a provider/model config reload — here triggered by other ?directory= clients connecting/reconnecting — disposes shared instances and interrupts fibers of in-flight SSE requests, including /api/event streams for sessions in unrelated directories. Differs from #52049 / #51216 in that the server is not restarted/replaced; differs from #48907 in that no skill loading is involved.

Minimal reproduction sketch

  1. Start shared server, connect client A with directory DA and an active long-running session streaming /api/event.
  2. From client B (directory DB), trigger provider config reload (e.g. connect/reconnect, or touch provider config).
  3. Observe A's /api/event stream terminate with InterruptError ... http.status=200 and the CLI exit without a terminal event.

Secondary observation (Windows-specific)

~38 occurrences of unhandled rejections like:

EPERM: operation not permitted, rename '...session.json.<pid>.<uuid>.tmp' -> '...session.json'

when multiple processes write shared session state concurrently — suggests atomic-rename on shared state files needs retry/serialization under Windows.

Related issues

Activity

  1. opencode-agent commented on Oct 10, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report! Before we try to reproduce it, could you describe briefly, in your own words, what you did, what you expected and what you saw? A lot of the current text is analysis and guesswork. Specifically, it would help to have:

    1. Exact steps you've confirmed reproduce it. For example: start the server, run opencode run --format json --session <id> ... in directory A, then do what from directory B (connect a client? edit the provider config?), and does A's run stop every time?
    2. For one run that exited silently: the exit code, anything printed to stderr, and ideally the output with --print-logs added.
    3. The server log lines around that moment, including any provider:updated / config reload entries right before the interrupt, so the link between the two can be seen.

    One note: the InterruptError ... GET /api/event ... http.status=200 lines at INFO level are written whenever an event-stream request ends by being interrupted, and that can also happen when the client closes the stream. So on their own they may be a result of the CLI exiting rather than its cause. That's why the steps and the CLI's own output matter here.

    You can reply here with the details, or edit the issue. If you edit it, please also leave a comment saying you've updated it, so we know you're done.

    Related issues I found, ordered by likelihood of being relevant:

  2. opencode-agent commented on Oct 13, 2026

    @opencode-agent
    Contributor

    We're closing this for now because we haven't heard back. To check whether a provider/model config reload from another directory really interrupts unrelated /api/event streams, we need a few things: steps you've confirmed reproduce it, the exit code, stderr and --print-logs output from one opencode run that exited silently, and the server log lines around that moment. Without them, the InterruptError ... http.status=200 lines could just as well come from the client closing the stream.

    If you can share those details, please reply here or open a new issue with them, and we'll take another look. The Windows EPERM rename problem you mentioned is already tracked in #51470. Thanks for the report!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions