anomalyco / anomalyco/opencode
Uncaught EIO/EPIPE on write crashes opencode when pty dies mid-write
@kommander is already working on this.
Since Aug 1, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Bug
opencode (v1.18.10, bun 1.3.14, Linux) crashes hard with an uncaught exception when the underlying pty/pipe goes away while opencode is mid-write to stdout. Happened 3 times in one day, always the same stack.
Stack trace
EIO: i/o error, write
fd: 13,
syscall: "write",
errno: -5,
code: "EIO"
at write (unknown:1:1)
at writeFast (internal:fs/streams:345:38)
at /$bunfs/root/chunk-ztxp1sde.js:95:38
at ~effect/Effect/evaluate (/$bunfs/root/chunk-datjqaqc.js:25:4492)
at runLoop (/$bunfs/root/chunk-datjqaqc.js:25:2045)
at evaluate (/$bunfs/root/chunk-datjqaqc.js:25:1435)
at /$bunfs/root/chunk-datjqaqc.js:25:5664
at processTicksAndRejections (native:7:39)
Also observed repeatedly as non-fatal EPIPE (errno -32) bursts on fd 12 in the same session, via the same writeFast path, before the fatal EIO hit fd 13.
Root cause (as far as I traced it)
I run opencode inside a zellij pane spawned via a layout's command "opencode" directive (not through an interactive login shell). When the zellij session dies/exits (pty torn down) while opencode is still writing its TUI output, bun's raw write() on the underlying fd throws synchronously (EIO/EPIPE) instead of opencode/bun handling it as a normal stream-close condition. Since this happens outside any try/catch in the effect runLoop, it's an uncaught exception and kills the whole process — no graceful shutdown, no partial-session recovery, nothing logged except the raw stderr dump.
Expected behavior
Writing to a dead pty/pipe (EIO/EPIPE) should be treated like any other "peer went away" condition — swallow it and begin/complete a clean shutdown (or at minimum emit a catchable error), not propagate as an uncaught exception that kills the process mid-session.
Repro (best guess, not confirmed minimal repro)
- Launch opencode as the
commandof a zellij pane (not via a login shell) — e.g.:pane { command "opencode" } - Let opencode run a TUI session, actively producing output (agent working, streaming tokens, etc.)
- Kill/detach/crash the zellij session out from under the pane while output is being written
- opencode dies with the EIO stack above, session progress lost, only recoverable via the stderr log
Workaround in use
Wrapping the zellij pane command as bash -lc "opencode" instead of a raw command "opencode" reduces exposure (gives opencode a shell-owned pty), but doesn't address the actual uncaught-throw-on-dead-pty behavior — if the terminal/pty dies for any other reason mid-write, the same crash should still reproduce.
Environment
- opencode 1.18.10
- bun 1.3.14
- Linux (Fedora), Hyprland
- Terminal multiplexer: zellij
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.