[BUG] statusLine context_window.used_percentage drops to 0 after an API error: synthetic assistant entries carry all-zero usage
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (related, but a different trigger: #62768 for the one-tick zero after
/compact, and #18241 for a percentage mismatch) - [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
When a turn fails with an API error (for example API Error: Can't reach the API server — check your internet or DNS (ENOTFOUND)), or when Claude Code writes No response requested., it appends a synthetic assistant message ("model": "<synthetic>") to the transcript. Every usage field on it is zero.
The statusLine payload takes context_window.used_percentage (and current_usage) from the last assistant message that has usage, and that is now the synthetic one. So the status line reports 0% context, and it keeps reporting 0% until the next successful reply. That can be hours: a session that sits idle after an outage shows "0% ctx" the whole time, while its real context is 200k–350k tokens.
/context is not affected. Only the statusLine payload is.
What Should Happen?
Synthetic entries (or any assistant entry whose input + cache usage total is 0) should be skipped when computing used_percentage and current_usage, so the value stays at the last real usage. Alternatively, send null ("unknown") instead of 0.
Error Messages/Logs
Sanitized transcript evidence from one machine, last 24h: 52 transcripts, 21 synthetic assistant entries, all 21 with all-zero usage (18 × the ENOTFOUND API error, 3 × "No response requested."). Three examples, each with the context of the previous real assistant message:
[
{"ts": "2026-10-10T12:21:26.832Z", "text": "API Error: Can't reach the API server — check your internet or DNS (ENOTFOUND)",
"usage": {"input_tokens": 0, "output_tokens": 0, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0},
"prev_real_context_tokens": 294839},
{"ts": "2026-10-10T08:24:50.689Z", "text": "No response requested.",
"usage": {"input_tokens": 0, "output_tokens": 0, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0},
"prev_real_context_tokens": 215736},
{"ts": "2026-10-10T09:45:31.728Z", "text": "API Error: Can't reach the API server — check your internet or DNS (ENOTFOUND)",
"usage": {"input_tokens": 0, "output_tokens": 0, "cache_read_input_tokens": 0, "cache_creation_input_tokens": 0},
"prev_real_context_tokens": 354472}
]
(prev_real_context_tokens = input + cache_read + cache_creation of the last non-synthetic assistant message before it.)
Steps to Reproduce
- Configure a
statusLinecommand that printscontext_window.used_percentagefrom stdin. - Work in a session until the context is clearly non-empty (e.g. 30%+).
- Make the next request fail with a network error (e.g. block the API host or go offline), so the turn ends with
API Error: Can't reach the API server …. - Restore the network and do not send another prompt.
- The status line now shows
0and stays at 0 until the next successful reply. The transcript's last assistant entry has"model": "<synthetic>"and all-zerousage.
Claude Model
Not model-specific (the synthetic entry is written client-side).
Is this a regression?
Unknown.
Claude Code Version
2.1.296 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other (Ghostty-based terminal), zsh
Additional Information
Our workaround: when the payload reports a zero total or a null percentage, the statusLine script recomputes the value from the transcript. It takes the last non-synthetic, non-sidechain assistant usage after the last compact boundary and divides by context_window_size. It prints INDETERMINATE rather than 0% when it can't.