Windows: claude exits without restoring console title, crashing Playwright driver startup (Assertion failed: process_title, src\win\util.c:412)

Resolved 💬 3 comments Opened Apr 23, 2026 by duggelz Closed May 28, 2026

Summary

On Windows, exiting claude (especially via Ctrl-C) leaves the Win32 console title in a state that crashes Playwright's bundled Node driver at startup with:

Assertion failed: process_title, file src\win\util.c, line 412

Per libuv #2667, libuv on Windows backs uv_get_process_title / uv_set_process_title with GetConsoleTitleW / SetConsoleTitleW. Claude Code mutates the title via process.title (which on Windows is SetConsoleTitle) and doesn't restore it on exit. The bad title persists in the conpty buffer for the Windows Terminal tab and trips libuv's assert(process_title) in any Node process that reads the title before its own cache is populated. This is the concrete bug the (stale, closed) feature request #21409 was implicitly warning about.

Repro

  1. Windows Terminal -> bash (MINGW64).
  2. claude -> wait for it to start -> Ctrl-C to exit.
  3. ```

uv run python -c "from playwright.sync_api import sync_playwright; sync_playwright().start()"
``
->
`
Assertion failed: process_title, file src\win\util.c, line 412
``

  1. Same command in a fresh tab works fine.

Diagnosis

  • env and stty -a are byte-identical between borked and fresh tabs (only WT_SESSION differs, expected per-tab).
  • reset and stty sane don't help -- they're termios/escape resets, not Win32 console state.
  • Vanilla Node does not reproduce: node -e "process.title" and node -p "process.title" succeed, presumably because Node's startup calls uv_set_process_title("node") early and the title getter then reads the cached value rather than calling GetConsoleTitleW. Playwright's driver evidently reads before any cache is populated.
  • Both of these clear the bad state (each performs a SetConsoleTitleW under the hood):
  • printf '\e]0;\a' (empty OSC 0)
  • node -e "process.title = 'foo'"

Workaround

Wrap claude in a shell function that resets the title on exit:

claude() {
  (
    trap 'printf "\e]0;\a" > /dev/tty 2>/dev/null' EXIT
    command claude "$@"
  )
}

Suggested fix

Either of:

  1. Save and restore the title. On startup, capture via GetConsoleTitleW; on SIGINT/SIGTERM/exit, restore via SetConsoleTitleW. Cleanup must run on Ctrl-C, not just normal exit.
  2. Stop using process.title on Windows. Use OSC 2 (\x1b]2;TITLE\x07) instead, as proposed in #21409. This is the standard VT sequence; every terminal emulator honors it; it doesn't poke Win32 console state and so can't leave libuv in a bad state.

(2) addresses both this bug and the cross-platform inconsistency that #21409 raised.

Environment

  • Windows 10 Pro 10.0.19045
  • Windows Terminal + Git Bash MINGW64 (MSYS=enable_pcon)
  • Claude Code v2.1.119
  • Playwright (Python) -- fails on sync_playwright().start() spawning the Node driver

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗