[BUG] [Desktop][Linux] titleBarOverlay applied to every window on Linux (Windows-only API) leaves untitled, unclosable 800x600 orphan windows
Summary
On Linux, Claude Desktop creates BrowserWindows with titleBarStyle: "hidden" and then
calls setTitleBarOverlay() on them. setTitleBarOverlay is Windows-only in Electron,
so the call throws on Linux and is swallowed. The result is a window whose native title bar
is hidden with nothing drawn in its place and no WM_NAME — an untitled, chrome-less
orphan window that the window manager cannot address.
The app's own code acknowledges the platform restriction:
titleBarOverlay: (e, t) => rle() && t && typeof t == "object"
? e.setTitleBarOverlay(t)
: !rle() && t && Pa("titleBarOverlay only works on Windows")
…but a separate call site applies it unconditionally to every window and discards the error:
ow.getAllWindows().forEach(o => {
if (AUe.get(o) !== i) try { o.setTitleBarOverlay(r), AUe.set(o, i) }
catch { _.info("Failed to set title bar overlay, this is probably expected") }
})
Evidence
~/.config/Claude/logs/main.log — 292 occurrences over 3 days, continuous:
[info] Failed to set title bar overlay, this is probably expected
Resulting window, via xprop / xdotool:
| id | size | WM_CLASS | WM_NAME | state |
|---|---|---|---|---|
| A | 898x1166 | com.anthropic.claude | Claude | viewable (the real window) |
| B | 800x600 | com.anthropic.claude | '' (empty) | viewable, renders blank |
Window B carries the real application class, not a helper class — it is a genuine app
window. 800x600 is Electron's untouched default BrowserWindow size, i.e. the window was
created and its chrome setup failed before anything else was applied.
Impact
- The window is not closable by normal means. With no title and no title bar,
wmctrl -ic
/ _NET_CLOSE_WINDOW are ignored. XKillClient would terminate the entire app's X
connection, taking every Claude window with it. The only safe remedy is xdotool windowunmap,
which hides rather than closes it.
- It is indistinguishable from the real window to automation. Any tool selecting a window
by application class and a size heuristic can pick the blank one. Input sent to it is
silently lost — it renders nothing and reports no error.
- Screen-reading/accessibility tooling sees a blank rectangle with no title to
disambiguate it from the real window.
Reproduction
- Run Claude Desktop on Linux (X11).
grep -c 'Failed to set title bar overlay' ~/.config/Claude/logs/main.log— non-zero.- `for w in $(xdotool search --class com.anthropic.claude); do
echo "$w '$(xdotool getwindowname $w)' $(xdotool getwindowgeometry $w | tail -1)"; done`
— one or more windows with an empty name at 800x600.
Suggested fix
Guard the call site the same way the setter is already guarded, rather than relying ontry/catch:
ow.getAllWindows().forEach(o => {
if (!rle()) return; // Windows only — skip entirely elsewhere
if (AUe.get(o) !== i) { o.setTitleBarOverlay(r); AUe.set(o, i) }
})
And on non-Windows platforms avoid pairing titleBarStyle: "hidden" with an overlay that
cannot be drawn — either keep the native decoration or render an in-page title bar — so
windows always carry a WM_NAME.
Environment
- Claude Desktop 1.24012.9 (Linux)
- Linux, X11, Cinnamon
- Electron 42.7.0 / Chromium 148 / Node 24.18