You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
server: non-service startup skips restart continuity for suspended sessions #56313
OpenCode's restart continuity sweep is only installed when the server is started through the managed --service path. A long-lived server started without that lifecycle path can leave suspended Sessions and in-flight background subagent jobs permanently stranded after a process restart: the child is not resumed, its completion is not delivered, and the parent remains silent.
This is distinct from the parent/child watcher reconstruction tracked in #36349. The issue here is that no restart sweep is installed at all for non-service startup.
Steps to reproduce
Start OpenCode using a non-service server/TUI process (without --service).
Start a background subagent and keep it in flight while the server process is terminated.
Start the same server again against the same persistent data directory.
Observe that the suspended child is not resumed and the parent receives no completion.
Repeat through opencode service start / --service and compare: the managed restart continuity path is installed there.
The relevant code path is installRestartContinuity, which is guarded by the presence of the lifecycle/service options.
Expected behavior
Every supported long-lived server startup should either install restart continuity or clearly document and surface that suspended Sessions and background jobs will not be recovered.
Actual behavior
Non-service startup has no restart sweep, so persisted in-flight work can remain indefinitely without a consumer.
Evidence
This was identified while investigating oh-my-opencode-slim issue #1560. In an isolated persistent-data instance, managed service restart recovery worked end to end; the missing lifecycle path is the deterministic difference for this failure mode.
You're asking for restart continuity (resuming suspended Sessions and in-flight background subagents) on long-lived servers started without --service, or failing that, for docs and a warning that they don't recover this work.
The code backs up what you describe: in packages/server/src/process.ts, installRestartContinuity runs only for the managed service. That looks deliberate, though. The code comment says the managed server owns restart continuity, and recent work has been narrowing automatic recovery for non-service processes, not widening it, because unexpected resumes caused problems. So I've filed this as a feature or design request rather than a bug. Maintainers will consider it, but I can't promise anything.
I propose making restart continuity an explicit server capability, with the existing managed-service behavior preserved, rather than enabling the sweep for every Node startup.
There is an important entry-point distinction at current dev (6e9c853):
ServerFetch.make already invokes the sweep when its layer is built, without that Node lifecycle. So “all non-service servers do not recover” would be an inaccurate contract for embedders.
For a bounded first change, I suggest exposing the startup recovery capability from the server (enabled for the managed path, disabled for non-service Node startup), then surfacing the disabled state in the long-lived foreground server/TUI flow with a concise explanation that restart alone will not resume interrupted work. stdio must retain its machine-readable startup protocol. Document the separate fetch-embedder responsibility alongside this, without changing its execution behavior. This addresses the issue's requested visible explanation without automatically taking over persisted work or promising that parent/child delivery is solved.
Broader non-service automatic recovery should be a separate opt-in design: it needs durable recovery eligibility plus cross-process owner-liveness/ownership semantics, and a decision about which execution environment is safe to restore. Merely removing if (lifecycle) or using a port/registration lock would not establish those guarantees for every writer of a shared database. I would coordinate that part with the existing ownership/eligibility work rather than duplicate it. #36349 remains a separate completion-delivery concern.
Could a maintainer approve the bounded capability/foreground explanation approach, or specify that non-service recovery itself should be the first implementation? Acceptance would cover the service/default/stdio/fetch boundary, unchanged recovery invocation counts, unchanged stdio output, and no persisted-state mutation from the explanation path. This is based on source inspection; I have not reproduced the original macOS scenario or run runtime tests for this proposal.
Activity
opencode-agent commentedon Oct 17, 2026
Thanks for the detailed write-up, @HeZ2z!
You're asking for restart continuity (resuming suspended Sessions and in-flight background subagents) on long-lived servers started without
--service, or failing that, for docs and a warning that they don't recover this work.The code backs up what you describe: in
packages/server/src/process.ts,installRestartContinuityruns only for the managed service. That looks deliberate, though. The code comment says the managed server owns restart continuity, and recent work has been narrowing automatic recovery for non-service processes, not widening it, because unexpected resumes caused problems. So I've filed this as a feature or design request rather than a bug. Maintainers will consider it, but I can't promise anything.Related issues:
Dante-dan commentedon Oct 20, 2026
I propose making restart continuity an explicit server capability, with the existing managed-service behavior preserved, rather than enabling the sweep for every Node startup.
There is an important entry-point distinction at current
dev(6e9c853):ServerProcess.startinstalls continuity only with a lifecycle. The CLI supplies that lifecycle only formode: "service";defaultandstdioskip it.ServerFetch.makealready invokes the sweep when its layer is built, without that Node lifecycle. So “all non-service servers do not recover” would be an inaccurate contract for embedders.SessionRestartexplicitly assumes the old claim owner is dead. Its active-session checks are local to the executor; they are not proof that another process sharing the database is dead. Background service resumes sessions still running on another server that shares the database #51213 demonstrates that distinction. Likewise, preserving the original recovery eligibility/configuration matters independently of owner death (Background service resumes opencode run --standalone sessions after the run was killed, without its permissions or step limit (runaway: 1,660 steps, ~$24) #55076 / fix(core): exclude standalone executions from restart recovery #55174).For a bounded first change, I suggest exposing the startup recovery capability from the server (enabled for the managed path, disabled for non-service Node startup), then surfacing the disabled state in the long-lived foreground server/TUI flow with a concise explanation that restart alone will not resume interrupted work.
stdiomust retain its machine-readable startup protocol. Document the separate fetch-embedder responsibility alongside this, without changing its execution behavior. This addresses the issue's requested visible explanation without automatically taking over persisted work or promising that parent/child delivery is solved.Broader non-service automatic recovery should be a separate opt-in design: it needs durable recovery eligibility plus cross-process owner-liveness/ownership semantics, and a decision about which execution environment is safe to restore. Merely removing
if (lifecycle)or using a port/registration lock would not establish those guarantees for every writer of a shared database. I would coordinate that part with the existing ownership/eligibility work rather than duplicate it. #36349 remains a separate completion-delivery concern.Could a maintainer approve the bounded capability/foreground explanation approach, or specify that non-service recovery itself should be the first implementation? Acceptance would cover the service/default/stdio/fetch boundary, unchanged recovery invocation counts, unchanged stdio output, and no persisted-state mutation from the explanation path. This is based on source inspection; I have not reproduced the original macOS scenario or run runtime tests for this proposal.