Skip to content

Sessions stuck as 'working' when idle status event is missed #220

Description

@dzianisv

Bug

When a prompt loop exits but the idle status event fails to fire (interrupted finalizer, scope teardown race, etc.), the session's `SessionStatus` stays at `busy` indefinitely. Clients connected over SSE see the session as "working" forever even though no runner is actually executing.

The same in-memory inconsistency appears between `SessionStatus` and `SessionRunState`: the status map says `busy`, but the runners map has no active runner for that session. `SessionRunState.cancel` already has the same defensive "no busy runner → set idle" check (`packages/opencode/src/session/run-state.ts:80`), but it only fires when `cancel` is invoked — nothing reconciles passively.

Reproduction

Within a single serve process:

  1. Start a prompt loop in a session.
  2. Force the loop to terminate without firing `onIdle` (kill the runner mid-execution, simulate a finalizer interrupt, or directly set `SessionStatus` to `busy` without an active runner).
  3. The session permanently shows `busy` in the UI and via the HTTP API; no recovery happens until the process restarts.

Proposed fix

Add a periodic reconciler that scans `SessionStatus.list()` and, for every non-idle status without a corresponding active runner in `SessionRunState`, resets the status to `idle`.

  • Periodic — 30s interval, forked fiber scoped to the serve lifetime.
  • Effect-native — exposed via `SessionRunState.reconcile()`, wired in `cli/cmd/serve.ts` via `Effect.repeat(Schedule.spaced(Duration.seconds(30)))` + `Effect.forkScoped`, matching the existing autoresume pattern.
  • Iterates known session directories with the autoresume pattern (`Session.listGlobal` + `InstanceStore.provide`) so it works per-instance even though serve.ts is `instance: false`.
  • Configurable via env: `OPENCODE_SERVE_RECONCILE_INTERVAL_S` and `OPENCODE_SERVE_RECONCILE_SCAN_LIMIT`.

History

Original fix landed on `fix/session-status-reconciliation` as commit `f62969219` against the pre-rewrite codebase. PR #208 was auto-closed by the contribution-guidelines bot on 2026-05-16 for missing PR-template sections — not rejected on merit. After the upstream-dev rebase, the patch no longer applied as-is; this issue tracks the Effect-native port.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions