majormonitoring-gapverifiedfirsthand
An out-of-credit error came back with exit 0, so empty batch runs looked like success
In a batch loop built on `claude -p`, running out of API credit printed "Credit balance is too low" to stdout and exited 0, so empty results piled up looking like successful runs.
Cause
The CLI was logged in to an API-billing organization rather than the subscription, and that organization's credit had run dry. On top of that, the CLI didn't treat the failure as an error; it returned it as normal output.
Consequence
Every claude -p call failed, and the batch had no way to tell from exit codes alone. Later, seeing the same message, the operator topped up the wrong billing account and put $5.50 where it couldn't help.
Fix
Re-running /login and choosing the subscription account fixed it, with no credit purchase needed. Batches no longer trust exit codes: every output is grepped for Credit balance is too low.
What happened
Repetitive work that needed an LLM judgment call per item was running as a
claude -p loop: call Claude Code non-interactively once per item, take the
result, move on. A very ordinary batch.
At some point, every claude -p call started failing. The batch didn’t stop.
The failure message, “Credit balance is too low,” went to stdout, and the exit
code was 0. From the loop’s point of view, each call finished cleanly and
returned something.
The chaos on the ground
Checking exit codes was completely useless here. Success and failure both exited 0 and both printed a string to stdout. The only difference was the content.
Digging in, the real cause sat one step before the balance itself. The CLI’s saved login pointed at an API-billing organization, not the subscription. That organization was out of credit and couldn’t receive overage credit either. Stripping environment variables didn’t help, because the problem was the stored login itself.
It didn’t end there. Later, an API-key call returned the same “Credit balance is too low.” Same words, so presumably the same wallet — and the operator topped up $5.50 on the subscription billing page. But API keys bill through a separate account, and that money did nothing for the API. The same message was pointing at two different wallets.
Root cause
- The CLI was logged in to an API-billing organization whose credit was gone.
claude -preports running out of credit not as an error but with exit 0 and a line on stdout, so an empty run was recorded in exactly the same shape as a successful one.- The message “Credit balance is too low” appears for both the CLI/app path and the API-key path. They bill from different places, and the wording gives no hint which one you’re looking at.
The fix
- Started
claude, ran/login, and picked the subscription account. That fixed it; no credit purchase was needed. - Batches no longer trust exit codes. Each output’s content is checked, and
grepping for
Credit balance is too lowis now mandatory. - While credit is out, work can be routed to subagents that run on the subscription side and need no API credit.
- When an API key returns the same message, check the balance in the API console rather than the app’s billing page, and make sure the right organization is selected. Same message does not mean same wallet.
Sources
- Firsthand account from the site operator. There is no public write-up to link to.