Windows: claude exits without restoring console title, crashing Playwright driver startup (Assertion failed: process_title, src\win\util.c:412)
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
- Windows Terminal -> bash (MINGW64).
claude-> wait for it to start -> Ctrl-C to exit.- ```
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
- Same command in a fresh tab works fine.
Diagnosis
envandstty -aare byte-identical between borked and fresh tabs (onlyWT_SESSIONdiffers, expected per-tab).resetandstty sanedon't help -- they're termios/escape resets, not Win32 console state.- Vanilla Node does not reproduce:
node -e "process.title"andnode -p "process.title"succeed, presumably because Node's startup callsuv_set_process_title("node")early and the title getter then reads the cached value rather than callingGetConsoleTitleW. Playwright's driver evidently reads before any cache is populated. - Both of these clear the bad state (each performs a
SetConsoleTitleWunder 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:
- Save and restore the title. On startup, capture via
GetConsoleTitleW; on SIGINT/SIGTERM/exit, restore viaSetConsoleTitleW. Cleanup must run on Ctrl-C, not just normal exit. - Stop using
process.titleon 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
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗