[BUG] A single failed statusLine invocation blanks the status row — last successful output is discarded

Status Open
Reported on v2.1.278
Maintainer reply None cached
Activity 0 comments · opened Sep 21, 2026

Summary

A custom statusLine command that fails once makes the whole status-line row vanish until the next successful invocation. Claude Code does not retain the last successful output, so any transient failure of the command is rendered as a blank row rather than a slightly stale one.

Because the status line is re-run on a 300 ms-debounced event stream plus the optional refreshInterval timer, a command with even a 1–2 % per-invocation failure rate produces a visible flicker every few minutes. The row disappears and reappears on its own, which reads as a Claude Code rendering bug rather than as a failure of the user's script.

Environment

  • Claude Code 2.1.278 (native installer)
  • Linux, bun 1.4.2
  • statusLine.refreshInterval: 10, several Claude Code sessions running concurrently on the same machine

Current behaviour

When the configured command finishes with a non-zero exit status, fails to spawn, exceeds the deadline, or exits 0 with empty stdout, the status-line text is replaced with nothing. The previously rendered text is discarded, not kept. The next successful invocation restores it.

Observed with a real status-line command that intermittently exits 1 with empty stdout under concurrency: the row vanished for one refresh cycle and came back, repeatedly, with nothing in the UI indicating that the command had failed.

Minimal reproduction

/tmp/flaky-statusline.sh:

#!/bin/sh
cat > /dev/null
# fail roughly one invocation in five
if [ $(( $(date +%s) % 5 )) -eq 0 ]; then exit 1; fi
echo "status line OK $(date +%T)"

settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "/tmp/flaky-statusline.sh",
    "refreshInterval": 1
  }
}

The row blanks on every failing invocation instead of holding the previous line. The same happens if the script is changed to exit 0 with no output, or to sleep 60 (deadline).

Expected behaviour

A single failed or empty invocation should not blank the row. Options, roughly in order of preference:

  1. Keep the last successful output and re-render it when an invocation fails or produces empty stdout. This is the behaviour users almost certainly expect from a status indicator, and the last-good text already appears to be tracked across mount/unmount.
  2. If the output must change on failure, surface something instead of nothing — e.g. dim the retained line, or keep it and log the failure at normal verbosity so --debug is not required to notice.
  3. At minimum, make the distinction configurable, e.g. statusLine.retainOnFailure: true.

Treating "exit 0 with empty stdout" as an explicit request for a blank row would be reasonable; treating a non-zero exit, a spawn failure, or a timeout the same way is what causes the flicker.

Why this matters beyond one script

Popular status-line tools are configured through a package-runner one-liner such as npx -y <pkg>@latest or bunx -y <pkg>@latest. A dist-tag is not cacheable, so those commands reach the network on every repaint, and several of them installing into the same shared temp directory from concurrent sessions collide with each other. Both produce exactly the transient non-zero exit this issue is about. Users then report the status line as intermittently broken in Claude Code, since nothing in the UI attributes the blank row to their command.

Retaining the last good output would make the status line robust against this entire class of transient command failure, regardless of which tool the user configured.

Related

  • #32917 — custom statusLine command executed but output intermittently not rendered (closed as not planned); the reporter suspected concurrent sessions as a factor. This issue proposes the concrete mitigation.
  • #93043 — statusLine stops rendering after an update (different: permanent, not transient).

View original on GitHub ↗