Description
Summary
A background shell launched through the shell tool was interrupted by a restart
of the local opencode service. The tool call then reported an internal
Shell.NotFoundError with no output file, and no log line explains that the
service went away or that the shell was lost.
Environment
- opencode version: 2.0.27 (
message="cli starting" version=2.0.27 channel=latest local=false args=["serve","--service"] role=cli) - OS: Windows 10.0.26200 (win32 x64)
- Terminal:
TERM=xterm-256color;TERM_PROGRAM/COLORTERMunset - Shell:
C:\WINDOWS\system32\cmd.exe(tool commands run under Windows PowerShell) - Install/channel: desktop app (
%LOCALAPPDATA%\Programs\@opencodedesktop\OpenCode.exe), CLI 2.0.27 under%APPDATA%\ai.opencode.desktop\cli\2.0.27 - Active plugins: none found (no
opencode.jsonin the workspace or~/.config/opencode)
Reproduction
Observed once; not yet reproduced deliberately.
- In a long-running session, launch a multi-minute command as a background shell.
- While it is pending, the local service restarts (the app goes away and comes
back, and the session resumes from a checkpoint). - The pending tool call finishes as
state="error"with the text
Shell.NotFoundError, and the output path announced for that shell id does not
exist on disk.
Expected Behavior
A tool call cut off by a service restart should say so ("the local service
restarted; this shell was interrupted"), and mark or re-run the shell instead of
surfacing an internal error type. The service lifecycle should appear in the log
(a stop or crash line), so the discontinuity is explainable.
Actual Behavior
-
Tool result verbatim:
<shell id="sh_1611f9c450017wxSgDNEze4sKc" state="error" command="...">Shell.NotFoundError</shell> -
The announced output file for that shell id was never created.
-
~/.local/share/opencode/log/opencode.log: the previous service run
(run=4ef7016f) ends at2026-10-21T03:36:57.474Zon an ordinary
spawning processline with no shutdown, error or crash line afterwards; the
next run (run=2fee6bf5) begins at2026-10-22T00:59:35.324Zwith
cli starting ... ["serve","--service"].
Additional Context
- Frequency: once so far. Later background shells ran normally, which was also the workaround.
- The session itself survived the restart (resumed from a checkpoint); only the
in-flight shell call was lost. - If the service stopping was expected (the app was closed, or the machine slept),
the issue is specifically the error surface plus the missing lifecycle log line.
Activity
opencode-agent commentedon Oct 22, 2026
Thanks for the report. I reproduced the
Shell.NotFoundErrorresult on 2.0.27 and on the latestdev(1b1ad48). I didn't need a service restart to get it.Steps:
sleep 600,background: true).<shell id="sh_…" state="error" command="sleep 600">Shell.NotFoundError</shell>. The TUI shows "Shell failed", and the output file for that shell id is deleted.The recording and the script below show this.
Going by the code, a real restart is handled differently: the service should report "Command cancelled because the server restarted" when it comes back up. So in your case the shell was probably removed or shut down inside the old service before it went away. I haven't looked into the missing stop or crash line in the log.
Related:
recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.jorgeferreira1 commentedon Oct 25, 2026
A related variant on 2.1.4 (Linux TUI) where the session gets nothing, not even
Shell.NotFoundError:background: true) and ends its turn. The session is now idle, waiting for the shell-finished notification.serve --servicerestarts. Here it was an auto-update 2.1.3 → 2.1.4 triggered by another TUI being opened.GET /api/shell/<id>/outputwith 404, and the TUI shows "Shell cancelled". But no synthetic message is added to the session: the startup sweep only notifies sessions that were busy ("The server restarted while you were working"). The idle session's last record staysidle.So an agent that is waiting on a background shell (an overnight supervisor, in our case) is never woken again, and nothing in the session says why. Expected: a shell lost on restart completes with an error notification that wakes the owning session, whether it was busy or idle.