Post-Mortem: Claude Max + OpenClaw Billing Errors from Stale OAuth and Isolated Cron Jobs

A self-hosted OpenClaw setup with Claude Max started returning billing error — API key has run out of credits despite being well under quota. Two days of debugging revealed two root causes and a kill chain that makes the failure appear random.
Root Cause 1: Stale OAuth Token Poisons Whole Provider
The auth-profiles.json had two entries: a valid anthropic:claude-cli OAuth profile and an anthropic:manual profile with an sk-ant-oat01-... token. When the manual token expired, OpenClaw didn't just fail that profile — it classified it as a provider-level billing failure and blacklisted the entire anthropic provider, skipping every model including the healthy OAuth profile. Logs showed:
reason: "billing" errorPreview: "Provider anthropic has billing issue (skipping all models)" chain_exhausted
The healthy OAuth profile with a valid refresh token was never tried.
Fix: Remove anthropic:manual entirely from auth-profiles.json and openclaw.json. Keep only anthropic:claude-cli.
Root Cause 2: Isolated Cron Jobs Hit a Separate Billing Bucket
OpenClaw has two execution paths:
- Main sessions — runs
/usr/bin/claudebinary, billed to Max/Pro subscription ✅ - Isolated/embedded runs — direct HTTP to Anthropic API, billed to Extra Usage bucket ❌
Cron jobs with sessionTarget: isolated spin up a standalone embedded agent that calls the Anthropic API directly via HTTP — without the Claude Code headers the CLI sends. Anthropic routes it to the Extra Usage bucket, a completely separate quota. With Extra Usage off, every isolated cron run returns a 400. OpenClaw then worsens it: one billing error sets disabledUntil ~24 hours forward in auth-state.json, locking out all requests — including normal chat — until cooldown fires. The lockout survives gateway restarts.
The Full Kill Chain
- Gateway restart → missed cron job queues for catch-up
- Isolated agent fires via embedded runner → direct HTTP call to Anthropic API (no CLI headers)
- Extra Usage bucket → 400 error
- OpenClaw locks auth profile for ~24h → all requests blocked including normal chat
Fixes
- Clear the billing lockout immediately:
python3 -c " import json with open('/home/USER/.openclaw/agents/main/agent/auth-state.json') as f: d = json.load(f) if 'usageStats' in d: for profile in d['usageStats']: d['usageStats'][profile].pop('disabledUntil', None) d['usageStats'][profile].pop('failureCounts', None) d['usageStats'][profile].pop('errorCount', None) d['usageStats'][profile].pop('disabledReason', None) d['usageStats'][profile].pop('lastFailureAt', None) with open('/home/USER/.openclaw/agents/main/agent/auth-state.json', 'w') as f: json.dump(d, f, indent=2) print('Cleared.') " openclaw gateway restart - Move all cron jobs from
isolatedtomain:python3 -c " import json with open('/home/USER/.openclaw/cron/jobs.json') as f: d = json.load(f) jobs = d if isinstance(d, list) else d.get('jobs', []) for j in jobs: if j.get('sessionTarget') == 'isolated': print(f'Fixing: {j["name"]}') j['sessionTarget'] = 'main' with open('/home/USER/.openclaw/cron/jobs.json', 'w') as f: json.dump(d, f, indent=2) print('Done.') "
Who it's for: Anyone self-hosting OpenClaw with Claude Max or Pro who sees random billing errors despite being under quota.
📖 Read the full source: r/openclaw
👀 See Also

How to Fix OpenClaw Response Times by Reducing Context Bloat
A developer resolved 10-minute response times in OpenClaw by reducing injected workspace files from 47,000 characters to 16,000 characters through file restructuring and configuration changes, including setting bootstrapMaxChars to 8000 and adding compaction safeguards.

Multi-Agent Architecture: Avoiding the Single-Agent Pitfall in AI Systems
A Reddit post identifies the common architectural mistake of using a single agent for multiple tasks, which leads to fragile systems requiring constant babysitting. The solution proposed is an orchestrator-specialist model where each agent has a narrow, specific role.

Optimizing Qwen 3.6 27B/35B on RTX 3090: Flags, Quantization, and Auto-Routing
A user shares his llama-server flags for Qwen 3.6 27B and 35B GGUF models on an RTX 3090 (24GB), reporting slow speeds for the 35B and unreliable code output from the 27B. The post asks for better quant, flag tuning, and auto model switching.

How to avoid unexpected OpenRouter costs in OpenClaw automation
A developer team accidentally spent $750 in 3 days on OpenRouter by defaulting to Claude Sonnet 4.6 ($3/M tokens) across all automation tasks. They reduced costs by 97% by changing default models, locking cron jobs and subagents to cheaper options, and reserving expensive models only for sensitive work.