Repository navigation
Description
Description
When running opencode serve on Windows and connecting with opencode attach from a remote client, the server process dies immediately with exit code 0xC000013A (STATUS_CONTROL_C_EXIT) when the attached TUI triggers:
session_interrupt(Escape key) — to stop a running AI generationapp_exit(Ctrl+C) — to exit the TUI
Exiting via Ctrl+X, Q (leader-key quit) does not crash the server.
Evidence
WinSW wrapper log:
2026-08-11 22:33:54,352 DEBUG - Stopping process 1228...
2026-08-11 22:33:54,403 DEBUG - Process 1228 canceled with code -1073741510.
2026-08-11 22:33:54,406 INFO - Finished OpenCodeServer
Exit code -1073741510 = 0xC000013A = STATUS_CONTROL_C_EXIT.
Server stderr:
^C^CError: Unexpected error
ServeError
The literal ^C characters confirm a console control event was generated inside the server process.
After crash — zombie sockets prevent restart:
The dead process leaves the listening socket in LISTENING state (see issue #32932), so WinSW restart attempts fail with ServeError: Unexpected error because the port cannot be rebound.
Steps to reproduce
- On Windows: start
opencode serve --hostname 0.0.0.0 --port 4096(as a service or directly) - On Linux: connect with
opencode attach http://<windows-ip>:4096 --dir <project> - Start an AI generation (ask a question)
- Press Escape to interrupt the generation
- Server process exits with STATUS_CONTROL_C_EXIT
Alternative reproduction:
3. Press Ctrl+C to exit the TUI
4. Server process exits with STATUS_CONTROL_C_EXIT
Control: Press Ctrl+X, Q to exit → server stays running (no crash).
Expected behavior
session_interrupt(Escape): server should stop the current AI generation without dyingapp_exit(Ctrl+C): server should disconnect the client without dying- The server process should continue running and accept new connections
Environment
- OpenCode: v1.18.16 (latest)
- Server OS: Windows 11 25H2 (Build 26200.8875), running as WinSW service
- Client OS: Linux (Ubuntu 24.04)
- Connection:
opencode attachover HTTP (LAN) - Bun: bundled with opencode binary
Analysis
The exit code STATUS_CONTROL_C_EXIT indicates the process received a CTRL_C_EVENT console control event. On Windows, when a Bun process receives SIGINT (or internally calls something equivalent to process.kill(process.pid, "SIGINT") to handle session cancellation), the Bun runtime translates this to GenerateConsoleCtrlEvent, which triggers the default handler — ExitProcess(STATUS_CONTROL_C_EXIT).
The opencode server likely uses SIGINT internally for session interruption. On Linux this works because a JavaScript signal handler is registered and catches it gracefully. On Windows, the same mechanism kills the process because the default console control handler takes precedence and there is no equivalent handler registered via SetConsoleCtrlHandler.
Suggested fix
- Register a
SetConsoleCtrlHandleron Windows that catchesCTRL_C_EVENTandCTRL_BREAK_EVENTand prevents the default handler from killing the process - Or: avoid using
process.kill(pid, "SIGINT")internally for session interruption on Windows — use a message-based cancellation instead - Related: fix graceful socket shutdown on exit ([Bug]: opencode serve does not release port on exit — zombie self-loopback connection locks LISTENING socket (Windows) #32932) so that even if the process dies, the port is released and the service can restart cleanly
Activity
github-actions commentedon Oct 11, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.