anomalyco / anomalyco/opencode

[Bug]: opencode serve on Windows crashes with STATUS_CONTROL_C_EXIT when attached TUI sends session_interrupt or app_exit

Open
#41,878 0 comments 0 reactions 1 assignee View on GitHub

@Hona is already working on this.

Since Aug 11, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

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:

  1. session_interrupt (Escape key) — to stop a running AI generation
  2. app_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

  1. On Windows: start opencode serve --hostname 0.0.0.0 --port 4096 (as a service or directly)
  2. On Linux: connect with opencode attach http://<windows-ip>:4096 --dir <project>
  3. Start an AI generation (ask a question)
  4. Press Escape to interrupt the generation
  5. 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 dying
  • app_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 attach over 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 SetConsoleCtrlHandler on Windows that catches CTRL_C_EVENT and CTRL_BREAK_EVENT and 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 (#32932) so that even if the process dies, the port is released and the service can restart cleanly

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.