[BUG] `claude -p "/usage" --output-format json` intermittently fails right after a long print-mode run — exit 5, or `is_error:false` envelope with no `result`
Environment
- Claude Code v2.1.235
- Linux (Debian container, ChromeOS Crostini)
- Subscription auth (claude.ai login, not an API key)
- Invoked non-interactively from a systemd user unit (bash,
set -uo pipefail) - A Stop hook is configured in
~/.claude/settings.json— noting because of #38651, though that variant is consistent and this one is intermittent
What happens
claude -p "/usage" --output-format json intermittently fails, in two shapes, observed three times on 2026-08-19 between 12:19Z and 14:19Z:
- Exit code 5 (twice). Stdout produced nothing usable. Our script discarded stderr (
2>/dev/null), so no error text was captured; the exit code was recovered from systemd afterset -ekilled the calling script:Main process exited, code=exited, status=5/NOTINSTALLED. - Exit 0 with a success-shaped envelope missing its payload (once):
is_error: false,num_turns: 0, and no.resultkey at all —jq -e '.result'fails on it.
The same command otherwise succeeds dozens of times a day in the same environment: it runs at the top of a 16-minute timer tick and has never needed more than one 15-second retry there.
The suspicious correlation
Both exit-5 failures happened seconds after a long print-mode run finished in the same working directory — a ~20–30 minute, ~100-turn claude -p call (an unattended build loop; the /usage read is its post-run bookkeeping). Failure rate immediately after such a call: 2 of 2. At any other time: ~0 across dozens of calls that day.
The date also coincides with status.claude.com incidents ("elevated errors", evening of Aug 18 and morning of Aug 19 UTC), so this may be a server-side error being wrapped rather than a client-side race — not distinguishable from outside.
Why it matters
The second variant is the worse one: a success-shaped envelope around a failure. Automation has to detect it by noticing a missing field on an is_error: false response. If the underlying request failed, the envelope should say is_error: true, and the exit code for failure should be consistent and documented (what does 5 mean?).
Related: #38623, #38706, #38805, #39053 (empty result string variants), #38651 (Stop-hook-triggered, consistent).
Repro
No deterministic repro found. The pattern that maximises the odds: finish a long (~100-turn) claude -p run, then immediately run claude -p "/usage" --output-format json in the same directory.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗