openclaw - 💡(How to fix) Fix formatBillingErrorMessage misfires for Anthropic Max OAuth — broadcasts "top up your API key" when there is no API key

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

When the gateway is configured to talk to Anthropic via Max OAuth (no API key, no credit balance), the gateway still routes certain transient/usage errors through formatBillingErrorMessage and broadcasts the resulting "API provider returned a billing error — your API key has run out of credits…" text to the user-facing channel (in our case, Telegram).

There is no API key. The user can't "top up" anything. The message is alarming, misleading, and lands in the chat where end users see it.

After ~60 seconds the OAuth-sync layer clears the underlying lockout state and the gateway recovers. By then the misleading message has already been delivered.

Error Message

When the gateway is configured to talk to Anthropic via Max OAuth (no API key, no credit balance), the gateway still routes certain transient/usage errors through formatBillingErrorMessage and broadcasts the resulting "API provider returned a billing error — your API key has run out of credits…" text to the user-facing channel (in our case, Telegram). 4. The string ("API provider returned a billing error — your API key has run out of credits, please top up at https://console.anthropic.com/settings/billing") is delivered to the configured channel.

  1. Real billing failure (API key user, hard credit-balance error) → keep the existing "top up" text.
  • In the billing-error classifier, branch on whether the Anthropic provider is configured with an API key vs Max OAuth. When OAuth, emit the neutral "temporary, recovering" message and suppress the credit-balance / top-up link. I searched the issues tracker for "billing error Max OAuth false alarm" and similar variants — 0 hits. If there's an existing issue I missed, please mark this as duplicate.

Root Cause

Max OAuth is the recommended path for individual users on Claude Pro/Max. The current copy assumes everyone uses an API key, which makes the gateway look broken every time a perfectly benign OAuth-side hiccup occurs. End users (especially non-engineers) interpret "your API key has run out of credits, please top up" literally and reach for a credit card or panic.

Fix Action

Fix / Workaround

Local workaround in place

On the affected machine we run a small node script before each gateway start that finds the dist file containing formatBillingErrorMessage (filename has a content hash; we match by content) and replaces the two return-string branches with a calm, OAuth-aware string. It's idempotent and re-applies after every npm update via a gateway.cmd shim. This works but obviously isn't a real fix — every user on Max OAuth has to ship the same patch.

Privacy

Logs and config redacted of bot tokens / OAuth tokens / Telegram IDs. Happy to share a sanitized log excerpt or the local patch script privately if helpful.

RAW_BUFFERClick to expand / collapse

Description

Bug type

Behavior bug (incorrect user-facing message; no crash)

Summary

When the gateway is configured to talk to Anthropic via Max OAuth (no API key, no credit balance), the gateway still routes certain transient/usage errors through formatBillingErrorMessage and broadcasts the resulting "API provider returned a billing error — your API key has run out of credits…" text to the user-facing channel (in our case, Telegram).

There is no API key. The user can't "top up" anything. The message is alarming, misleading, and lands in the chat where end users see it.

After ~60 seconds the OAuth-sync layer clears the underlying lockout state and the gateway recovers. By then the misleading message has already been delivered.

OpenClaw version

2026.5.10-beta.5 — but the same code path has been present across earlier 2026.4.x / 2026.5.x releases.

Operating system

Windows 11 (build 10.0.26200). Also reproducible on macOS based on the shape of the upstream code path; the OS isn't the load-bearing variable here.

Environment

  • gateway: mode=local, bind=loopback, port=18789
  • Anthropic provider configured via Max OAuth, not an API key
  • No anthropicApiKey set anywhere in openclaw.json
  • Channel: telegram (any outbound channel exhibits the same behavior — the bug is in the message-shaping layer, not the channel)

Steps to reproduce

  1. Configure the Anthropic provider with Max OAuth (the standard claude /login flow, no API key).
  2. Let a session run until the OAuth token approaches expiry, OR force a transient 429 / usage-cap response from Anthropic.
  3. The gateway's classifier categorizes the response as "billing-shaped" and formatBillingErrorMessage formats the user-facing string.
  4. The string ("API provider returned a billing error — your API key has run out of credits, please top up at https://console.anthropic.com/settings/billing") is delivered to the configured channel.
  5. ~60 seconds later the OAuth-sync layer rotates the token and the gateway recovers normally. The misleading message stays in the channel history.

Expected behavior

Under Max OAuth, the gateway should not emit "your API key has run out of credits" because there is no API key. The right user-facing message is something like "Temporary upstream issue — recovering, please try again in a minute" (which is exactly what the recovery layer ends up doing anyway).

More fundamentally, the upstream classifier should distinguish:

  1. Real billing failure (API key user, hard credit-balance error) → keep the existing "top up" text.
  2. OAuth-related transient (Max OAuth user, token expiry / rate limit / usage cap) → emit a neutral "temporary, recovering" message and let the OAuth-sync layer do its job.

Actual behavior

Both classes get the same "top up your API key" message, which is wrong and high-visibility for Max OAuth users.

Why this matters

Max OAuth is the recommended path for individual users on Claude Pro/Max. The current copy assumes everyone uses an API key, which makes the gateway look broken every time a perfectly benign OAuth-side hiccup occurs. End users (especially non-engineers) interpret "your API key has run out of credits, please top up" literally and reach for a credit card or panic.

Local workaround in place

On the affected machine we run a small node script before each gateway start that finds the dist file containing formatBillingErrorMessage (filename has a content hash; we match by content) and replaces the two return-string branches with a calm, OAuth-aware string. It's idempotent and re-applies after every npm update via a gateway.cmd shim. This works but obviously isn't a real fix — every user on Max OAuth has to ship the same patch.

Suggested fix at the source

  • In the billing-error classifier, branch on whether the Anthropic provider is configured with an API key vs Max OAuth. When OAuth, emit the neutral "temporary, recovering" message and suppress the credit-balance / top-up link.
  • Alternatively: tighten the classifier so that OAuth-side 401/429/usage-cap responses don't get routed through formatBillingErrorMessage at all.

I'm happy to send a PR if maintainers want to point me at the preferred shape (single branch in formatBillingErrorMessage, or earlier in the classifier).

Search for prior art

I searched the issues tracker for "billing error Max OAuth false alarm" and similar variants — 0 hits. If there's an existing issue I missed, please mark this as duplicate.

Impact and severity

  • Affected: any user on Anthropic Max OAuth (the recommended individual path).
  • Severity: medium. The gateway recovers on its own, but the misleading user-facing message can trigger billing-related actions (or panic) for end users.
  • Frequency: every OAuth-side hiccup that crosses the classifier's thresholds — in our observation, ~5+ times across several weeks of normal use.

Privacy

Logs and config redacted of bot tokens / OAuth tokens / Telegram IDs. Happy to share a sanitized log excerpt or the local patch script privately if helpful.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Under Max OAuth, the gateway should not emit "your API key has run out of credits" because there is no API key. The right user-facing message is something like "Temporary upstream issue — recovering, please try again in a minute" (which is exactly what the recovery layer ends up doing anyway).

More fundamentally, the upstream classifier should distinguish:

  1. Real billing failure (API key user, hard credit-balance error) → keep the existing "top up" text.
  2. OAuth-related transient (Max OAuth user, token expiry / rate limit / usage cap) → emit a neutral "temporary, recovering" message and let the OAuth-sync layer do its job.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix formatBillingErrorMessage misfires for Anthropic Max OAuth — broadcasts "top up your API key" when there is no API key