majormonitoring-gapverifiedfirsthand
残高切れのエラーが exit 0 で返り、空振りが成功に見えた
`claude -p` を回すバッチで、APIクレジットが尽きると「Credit balance is too low」が標準出力に出て終了コード0で返り、中身のない結果が成功扱いで積み上がった。
原因
CLIのログインが、サブスクリプションではなくAPI課金の組織を向いており、その組織のクレジットが枯渇していた。しかもCLIはこの失敗をエラー扱いにせず、正常終了の出力として返していた。
結果
claude -p が一律で失敗し、バッチの出力は終了コードだけでは成功と見分けがつかなかった。後日、同じ文言を見た運営者が別の課金窓口に入金してしまい、$5.50が効かない側に入った。
対策
/login でサブスクリプション側のアカウントを選び直して解決した。クレジット購入は不要だった。バッチでは終了コードを信じず、各出力に Credit balance is too low が含まれていないかを必ず grep する。
何が起きたか
項目ごとにLLMの判断が要る繰り返し作業を、claude -p のループで回していた。
Claude Code を非対話で1回ずつ呼び、結果を受け取って次へ進む。よくある
バッチの形だ。
ある時点から、claude -p は一律で失敗していた。ところがバッチは止まらない。
失敗の文言「Credit balance is too low」は標準出力に出て、終了コードは0だった。
ループから見れば、毎回きちんと正常終了して、何かを返している。
現場の混乱
終了コードで成否を見る作りは、ここで完全に無力になった。成功も失敗も exit 0 で、どちらも標準出力に文字列を返す。違いは中身だけだ。
調べていくと、原因は残高そのものより手前にあった。CLIのログイン資格情報が、 サブスクリプションではなくAPI課金の組織を向いていた。その組織はクレジットが 枯渇しており、超過分の付与も受けられない状態だった。環境変数を外しても 直らない。保存済みのログインそのものの問題だったからだ。
話はここで終わらなかった。後日、今度はAPIキー経由の呼び出しで同じ 「Credit balance is too low」が出た。同じ文言なので同じ財布だと思い、運営者は サブスクリプション側の課金画面に$5.50を入金した。だがAPIキーの課金元は 別の窓口で、その入金ではAPIは動かない。同じ文言が、別々の財布を指していた。
原因
- CLIのログインが、クレジットの尽きたAPI課金の組織を向いていた。
claude -pは残高切れをエラーとして返さず、exit 0 と標準出力で返す。 そのため「空振り」が「成功」と同じ形で記録された。- 「Credit balance is too low」という同じ文言が、CLI/アプリ経由とAPIキー経由の どちらでも出る。課金元が違うのに、文言からは区別できない。
対策
claudeを起動して/loginを実行し、サブスクリプション側のアカウントを 選び直した。これで解決し、クレジットの購入は要らなかった。- バッチでは終了コードを信じない。各出力の中身を検証し、
Credit balance is too lowが含まれていないかを grep するのを必須にした。 - 残高切れの間の代替として、サブスクリプション側で動くサブエージェント (クレジット不要)に作業を回す。
- APIキーが同じ文言を返したときは、アプリ側ではなくAPIコンソール側の残高と、 組織の切り替えが正しいかを確かめる。文言が同じでも財布は同じとは限らない。
出典
- 運営者自身が起こした事故の一次記録です。外部に公開された元記事はありません。