openclaw - ✅(Solved) Fix [Bug]: Billing cooldown skip path bypasses isBillingErrorMessage() — users see generic error instead of billing message [5 pull requests, 1 comments, 2 participants]

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…
GitHub stats
openclaw/openclaw#66314Fetched 2026-04-15 06:26:41
View on GitHub
Comments
1
Participants
2
Timeline
11
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×5labeled ×2closed ×1commented ×1

When all model-fallback candidates are skipped due to billing cooldown, the user sees a generic error ("Something went wrong") instead of BILLING_ERROR_USER_MESSAGE. This commonly occurs with OAuth-authenticated Anthropic accounts that exhaust their personal "extra usage" quota, the cooldown-generated message "Provider X has billing issue (skipping all models)" does not match any pattern in isBillingErrorMessage().

Error Message

When all model-fallback candidates are skipped due to billing cooldown, the user sees a generic error ("Something went wrong") instead of BILLING_ERROR_USER_MESSAGE. This commonly occurs with OAuth-authenticated Anthropic accounts that exhaust their personal "extra usage" quota, the cooldown-generated message "Provider X has billing issue (skipping all models)" does not match any pattern in isBillingErrorMessage(). 3. A background/scheduled agent task hits the billing error first, putting the auth profile into billing cooldown. 5. Observe the user-facing error message. "⚠️ API provider returned a billing error — your API key has run out of credits or has an insufficient balance. Check your provider's billing dashboard and top up or switch to a different API key."

First failure: raw billing error, isBillingErrorMessage() matches correctly:

[agent] embedded run agent end: runId=e8520f5d-... isError=true model=claude-opus-4-6 provider=anthropic error=LLM request rejected: You're out of extra usage. Add more at claude.ai/settings/usage and keep going.

  • Severity: Medium: misleading error message, users cannot diagnose the billing issue unless read logs The OAuth path makes this especially common for personal "extra usage" quotas on claude.ai are generally smaller than typical org API budgets, so users hit this more frequently. The Anthropic error is: 400 {"type":"error","error":{"type":"invalid_request_error","message":"You're out of extra usage. Add more at claude.ai/settings/usage and keep going."}}

Root Cause

  • Affected: All OAuth-authenticated users who exhaust their personal Anthropic usage quota; also affects API key setups that run out of credits
  • Severity: Medium: misleading error message, users cannot diagnose the billing issue unless read logs
  • Frequency: Always reproduces after the first billing failure triggers cooldown; common with OAuth since personal usage caps are hit more frequently
  • Consequence: Users see "Something went wrong" with no actionable guidance (e.g. "top up at claude.ai/settings/usage"), repeatedly retry without understanding the root cause

Fix Action

Fixed

PR fix notes

PR #66315: fix(agents): detect billing from FallbackSummaryError structured reasons

Description (problem / solution / changelog)

Summary

  • Problem: When auth profiles enter billing cooldown, model-fallback skips all candidates with "Provider X has billing issue (skipping all models)". This message does not match any pattern in isBillingErrorMessage(), so users see "Something went wrong while processing your request" instead of BILLING_ERROR_USER_MESSAGE.
  • Why it matters: Only the very first billing failure (containing raw "out of extra usage") is detected correctly. Every subsequent attempt, which is the majority of what users see falls through to the generic error path. Especially common with OAuth users who exhaust personal Anthropic "extra usage" quotas.
  • What changed: Added isPureBillingSummary() in agent-runner-execution.ts that checks the structured attempt.reason === "billing" on FallbackSummaryError, used as a fast-path before isBillingErrorMessage() string matching. Added test covering this path.
  • What did NOT change (scope boundary): isBillingErrorMessage() patterns in failover-matches.ts are untouched. BILLING_ERROR_USER_MESSAGE text is unchanged. No changes to model-fallback logic itself.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #66314
  • Related #48526, #64224, #64308, #62375, #61608
  • This PR fixes a bug or regression

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: agent-runner-execution.ts line 1337 classifies billing errors using isBillingErrorMessage(message) which string-matches the formatted FallbackSummaryError message. When all candidates are skipped due to billing cooldown, the message contains "has billing issue (skipping all models)" none of the patterns in ERROR_PATTERNS.billing match this string.
  • Missing detection / guardrail: The rate-limit path already uses structured FallbackSummaryError data via isPureTransientRateLimitSummary() (checking attempt.reason), but the billing path had no equivalent and relied solely on string matching.
  • Contributing context (if known): PR #61608 added "out of extra usage" to the billing patterns, fixing detection for the raw Anthropic API error. But the cooldown-generated skip message uses different wording that was never added to the pattern list.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/auto-reply/reply/agent-runner-execution.test.ts
  • Scenario the test should lock in: FallbackSummaryError where every attempt.reason === "billing" (cooldown skip path) must return BILLING_ERROR_USER_MESSAGE, not the generic fallback.
  • Why this is the smallest reliable guardrail: Unit test directly verifies the classification logic in the catch block without needing a live provider or gateway.
  • Existing test that already covers this (if any): "does not show a rate-limit countdown for mixed-cause fallback exhaustion" covers the mixed billing+rate_limit case (which should NOT be classified as pure billing). The new test covers the pure-billing case.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

When all model candidates are skipped due to billing cooldown, users now see:

⚠️ API provider returned a billing error — your API key has run out of credits or has an insufficient balance. Check your provider's billing dashboard and top up or switch to a different API key.

Instead of:

⚠️ Something went wrong while processing your request. Please try again, or use /new to start a fresh session.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

Before:
[billing cooldown] -> FallbackSummaryError("...has billing issue...")
    -> isBillingErrorMessage() = false
    -> buildExternalRunFailureText()
    -> "Something went wrong"

After:
[billing cooldown] -> FallbackSummaryError(attempts[].reason="billing")
    -> isPureBillingSummary() = true
    -> BILLING_ERROR_USER_MESSAGE

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: Debian 12 (Bookworm) — Docker container (ghcr.io/openclaw/openclaw)
  • Runtime/container: Docker
  • Model/provider: anthropic/claude-opus-4-6, anthropic/claude-sonnet-4-6 (OAuth)
  • Integration/channel (if any): Web UI / gateway
  • Relevant config (redacted): Single-provider setup with Anthropic OAuth authentication

Steps

  1. Configure OpenClaw with Anthropic provider using OAuth authentication.
  2. The personal "extra usage" quota on claude.ai becomes exhausted.
  3. A background/scheduled agent task hits the billing error first, putting the auth profile into billing cooldown.
  4. User sends a message, all candidates are skipped due to billing cooldown.
  5. Observe the user-facing error message.

Expected

  • User sees BILLING_ERROR_USER_MESSAGE on every billing failure, including cooldown skips.

Actual

  • User sees generic "Something went wrong while processing your request" with no billing context.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)
# Cooldown skip path:  isBillingErrorMessage() misses this:
[model-fallback] decision=skip_candidate reason=billing detail=Provider anthropic has billing issue (skipping all models)
Embedded agent failed before reply: All models failed (2): anthropic/claude-opus-4-6: Provider anthropic has billing issue (skipping all models) (billing) | anthropic/claude-sonnet-4-6: Provider anthropic has billing issue (skipping all models) (billing)

Test results: 31/31 pass in agent-runner-execution.test.ts, 150/150 pass in related billing/error tests.

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: New test confirms pure-billing FallbackSummaryError returns BILLING_ERROR_USER_MESSAGE. Ran full test suites for agent-runner-execution.test.ts (31 pass), pi-embedded-helpers.isbillingerrormessage.test.ts and formatassistanterrortext.test.ts (150 pass).
  • Edge cases checked: Mixed-cause summary (billing + rate_limit) is NOT classified as pure billing, existing test "does not show a rate-limit countdown for mixed-cause fallback exhaustion" still passes.
  • What you did not verify: Live end-to-end test with an actual exhausted OAuth account. The fix is a classification-only change with no side effects on the model-fallback or auth-profile logic.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps:

Risks and Mitigations

None

Changed files

  • src/auto-reply/reply/agent-runner-execution.test.ts (modified, +59/-0)
  • src/auto-reply/reply/agent-runner-execution.ts (modified, +15/-1)

PR #66340: fix(billing): recognize billing cooldown skip messages as billing errors

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Billing cooldown skip messages (e.g., "Provider X has billing issue") were not recognized by isBillingErrorMessage(), causing the system to display a generic error instead of the specific billing error message.
  • Why it matters: Users see "Something went wrong" instead of actionable billing instructions ("API provider returned a billing error..."), leading to poor user experience and confusion.
  • What changed: Added regex patterns /has billing issue/i and /skipping all models/i to ERROR_PATTERNS.billing in src/agents/pi-embedded-helpers/failover-matches.ts.
  • What did NOT change (scope boundary): No changes to the billing cooldown logic itself, error generation, or other error classification patterns.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #66314

User-visible / Behavior Changes

Users encountering a billing cooldown (where all models are skipped) will now see the specific BILLING_ERROR_USER_MESSAGE ("API provider returned a billing error — your API key has run out of credits or has an insufficient balance...") instead of the generic "Something went wrong" message.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: N/A (AI-generated)
  • Runtime/container: N/A
  • Model/provider: Anthropic (OAuth)
  • Integration/channel (if any): N/A
  • Relevant config (redacted): N/A

Steps

  1. Configure OpenClaw with an Anthropic provider using OAuth authentication.
  2. Exhaust the personal "extra usage" quota to trigger a billing error.
  3. Allow a background or scheduled agent task to hit the billing error first, putting the auth profile into billing cooldown.
  4. Send a user message that attempts to use the provider.
  5. Observe the error message displayed to the user.

Expected

User sees: "⚠️ API provider returned a billing error — your API key has run out of credits or has an insufficient balance. Check your provider's billing dashboard and top up or switch to a different API key."

Actual

Before fix: User sees "⚠️ Something went wrong while processing your request. Please try again, or use /new to start a fresh session." After fix: User sees the expected billing message.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: local scoped validation and targeted checks for the changed area passed
  • Edge cases checked: relevant changed-path scenarios covered by selected validation
  • What you did not verify: full repository integration coverage beyond the selected validation scope

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Remove the two new regex lines (/has billing issue/i, /skipping all models/i) from ERROR_PATTERNS.billing in src/agents/pi-embedded-helpers/failover-matches.ts.
  • Files/config to restore: src/agents/pi-embedded-helpers/failover-matches.ts
  • Known bad symptoms reviewers should watch for: Users reverting to seeing generic "Something went wrong" errors during billing cooldown scenarios.

Risks and Mitigations

Risk: The new regex patterns could theoretically match non-billing error strings containing "has billing issue" or "skipping all models". Mitigation: The patterns are derived from specific internal log messages generated by the billing cooldown logic ("Provider X has billing issue (skipping all models)"), making false positives unlikely.

Changed files

  • src/agents/pi-embedded-helpers/failover-matches.ts (modified, +3/-0)

PR #66363: fix(reply): classify billing cooldown summaries

Description (problem / solution / changelog)

Summary

  • Problem: pure billing-cooldown fallback summaries are classified from message text only, so users get the generic failure text instead of billing guidance.
  • Why it matters: exhausted Anthropic OAuth/API-key users keep retrying without actionable billing guidance even though every fallback attempt is already tagged reason="billing".
  • What changed: billing classification now uses FallbackSummaryError.attempts[*].reason for pure billing summaries and adds a regression test for the cooldown summary path.
  • What did NOT change (scope boundary): no provider matching patterns, rate-limit handling, or fallback selection behavior changed.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #66314
  • Related #61608
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: runAgentTurnWithFallback only called isBillingErrorMessage(message), but billing cooldown summaries use generic text like Provider anthropic has billing issue (skipping all models) while still carrying structured attempt.reason === "billing" metadata.
  • Missing detection / guardrail: there was a structured helper for pure transient rate-limit summaries, but no equivalent structured billing summary classification.
  • Contributing context (if known): this is especially visible on Anthropic OAuth accounts where personal extra-usage caps are hit and the cooldown summary repeats for hours.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/auto-reply/reply/agent-runner-execution.test.ts
  • Scenario the test should lock in: a pure billing FallbackSummaryError with cooldown summary text still returns BILLING_ERROR_USER_MESSAGE.
  • Why this is the smallest reliable guardrail: the bug lives in the final user-facing classification branch, so the smallest reliable test is a runner-level summary error unit test.
  • Existing test that already covers this (if any): the existing mixed-cause fallback exhaustion test already guards against false rate-limit messaging for summary errors.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Users hitting pure billing cooldown summaries now see the billing guidance text instead of the generic "Something went wrong" message.

Diagram (if applicable)

Before:
billing cooldown summary -> string matcher misses it -> generic failure text

After:
billing cooldown summary -> all attempts tagged billing -> billing guidance text

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS 26.4.1
  • Runtime/container: Node 22 / pnpm workspace checkout
  • Model/provider: reproduced via unit test using Anthropic billing-cooldown summary payload
  • Integration/channel (if any): WhatsApp test fixture
  • Relevant config (redacted): N/A

Steps

  1. Throw a FallbackSummaryError whose attempts are all tagged reason: "billing" and whose message uses the cooldown summary wording.
  2. Run runAgentTurnWithFallback.
  3. Inspect the final user-facing reply text.

Expected

  • The runner returns BILLING_ERROR_USER_MESSAGE.

Actual

  • Before this fix, the runner returned the generic failure text because the billing check only string-matched the summary message.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: ran npx --yes pnpm exec vitest run src/auto-reply/reply/agent-runner-execution.test.ts -t "billing cooldown fallback exhaustion".
  • Edge cases checked: kept mixed-cause fallback summaries on the generic path; only all-billing summaries take the billing guidance branch.
  • What you did not verify: live provider cooldown behavior outside the unit test harness.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: mixed-cause fallback summaries could be over-classified as billing.
    • Mitigation: the new helper only returns billing when every summary attempt is tagged billing.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/auto-reply/reply/agent-runner-execution.test.ts (modified, +58/-0)
  • src/auto-reply/reply/agent-runner-execution.ts (modified, +11/-1)

PR #66536: fix(agents): recognize billing-cooldown skip messages as billing errors

Description (problem / solution / changelog)

Fixes #66314

Problem

When all model-fallback candidates are skipped due to billing cooldown, users see a generic "Something went wrong" instead of the proper billing error message.

Trace:

  1. A billing error causes a profile to enter cooldown with reason: "billing"
  2. On the next request, model-fallback.ts skips all candidates and emits:
    Provider anthropic has billing issue (skipping all models)
  3. formatAssistantErrorText()isBillingErrorMessage()returns false
  4. The message falls through to the generic error path

isBillingErrorMessage returned false because:

  • No 402/payment/credits keyword is present
  • BILLING_ERROR_HEAD_RE anchors to messages starting with "billing" or "error", but this message starts with "Provider"

Fix

Add "has billing issue" to ERROR_PATTERNS.billing in failover-matches.ts.

The substring has ${inferredReason} issue is the exact template used by model-fallback.ts (lines 592 and 611). It is specific to this internal code path and will not produce false positives against real provider API responses.

Changes

FileChange
src/agents/pi-embedded-helpers/failover-matches.tsAdd "has billing issue" to ERROR_PATTERNS.billing
src/agents/pi-embedded-helpers.isbillingerrormessage.test.tsAdd test covering the three provider variants emitted by model-fallback.ts

Test plan

  • pnpm test src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts — new test case passes
  • Existing billing/auth false-positive tests remain green (the new pattern only touches billing classification)
  • With an Anthropic OAuth account that has exhausted extra usage, the next agent turn shows BILLING_ERROR_USER_MESSAGE instead of the generic error

Changed files

  • src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts (modified, +14/-0)
  • src/agents/pi-embedded-helpers/failover-matches.ts (modified, +2/-0)

PR #259: 🦅 Scout: Critical Inherited Defect Report - 2026-04-14

Description (problem / solution / changelog)

Upstream Issue #66314: Billing cooldown bypasses fallback classification

  • Location in our code: src/agents/pi-embedded-helpers/failover-matches.ts lines 47-55
  • Observed Behavior: The ERROR_PATTERNS.billing object lacks a pattern to match the cooldown-generated skip message has billing issue. When a provider hits a persistent billing error and enters cooldown, subsequent fallback skips are misclassified by isBillingErrorMessage(). The user receives a generic Something went wrong error and an infinite retry loop occurs instead of a proper billing fallback error message.
  • Expected Behavior: isBillingErrorMessage() should explicitly recognize the cooldown-generated has billing issue message, correctly routing the fallback chain to deliver the persistent BILLING_ERROR_USER_MESSAGE to the user.
  • Impact Severity: HIGH - Breaks core functionality for users exhausting personal quotas, hiding actionable feedback and trapping the agent loop.

PR created automatically by Jules for task 6557759461051907800 started by @MillionthOdin16

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

Summary by CodeRabbit

  • Documentation
    • Added internal documentation for known error handling patterns to aid maintainers in identifying and addressing related issues during future updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Changed files

  • .jules/scout.md (added, +4/-0)

Code Example

# First failure: raw billing error, isBillingErrorMessage() matches correctly:
[agent] embedded run agent end: runId=e8520f5d-... isError=true model=claude-opus-4-6 provider=anthropic error=LLM request rejected: You're out of extra usage. Add more at claude.ai/settings/usage and keep going.
[agent] auth profile failure state updated: runId=e8520f5d-... profile=sha256:154a23a3efe6 provider=anthropic reason=billing window=disabled

# All subsequent failures: cooldown skip message, isBillingErrorMessage() does NOT match:
[model-fallback] model fallback decision: decision=skip_candidate requested=anthropic/claude-opus-4-6 candidate=anthropic/claude-opus-4-6 reason=billing next=anthropic/claude-sonnet-4-6 detail=Provider anthropic has billing issue (skipping all models)
[model-fallback] model fallback decision: decision=skip_candidate requested=anthropic/claude-opus-4-6 candidate=anthropic/claude-sonnet-4-6 reason=billing next=none detail=Provider anthropic has billing issue (skipping all models)
Embedded agent failed before reply: All models failed (2): anthropic/claude-opus-4-6: Provider anthropic has billing issue (skipping all models) (billing) | anthropic/claude-sonnet-4-6:
Provider anthropic has billing issue (skipping all models) (billing)

# This pattern repeats every 30 minutes for hours:
2026-04-13T22:41:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-13T23:11:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-13T23:41:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-14T00:11:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-14T00:41:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-14T01:11:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When all model-fallback candidates are skipped due to billing cooldown, the user sees a generic error ("Something went wrong") instead of BILLING_ERROR_USER_MESSAGE. This commonly occurs with OAuth-authenticated Anthropic accounts that exhaust their personal "extra usage" quota, the cooldown-generated message "Provider X has billing issue (skipping all models)" does not match any pattern in isBillingErrorMessage().

Steps to reproduce

  1. Configure OpenClaw with Anthropic provider using OAuth authentication.
  2. The personal "extra usage" quota on claude.ai becomes exhausted (or is already exhausted).
  3. A background/scheduled agent task hits the billing error first, putting the auth profile into billing cooldown.
  4. User sends a message, all candidates are skipped due to billing cooldown.
  5. Observe the user-facing error message.

Expected behavior

On subsequent failures after billing cooldown kicks in, users should see BILLING_ERROR_USER_MESSAGE: "⚠️ API provider returned a billing error — your API key has run out of credits or has an insufficient balance. Check your provider's billing dashboard and top up or switch to a different API key."

Actual behavior

After the first billing failure, all subsequent retries show a generic message: "⚠️ Something went wrong while processing your request. Please try again, or use /new to start a fresh session."

<img width="1140" height="284" alt="Image" src="https://github.com/user-attachments/assets/64e3434e-9a26-4d2e-9be7-275a13f8f884" />

The structured FallbackSummaryError carries attempt.reason="billing" for every attempt, but the isBilling check at agent-runner-execution.ts only uses isBillingErrorMessage() string-matching, which does not recognise "has billing issue (skipping all models)".

OpenClaw version

2026.4.9

Operating system

Debian 12

Install method

Docker

Model

anthropic/claude-opus-4-6, anthropic/claude-sonnet-4-6

Provider / routing chain

openclaw -> anthropic (OAuth)

Additional provider/model setup details

No response

Logs, screenshots, and evidence

# First failure: raw billing error, isBillingErrorMessage() matches correctly:
[agent] embedded run agent end: runId=e8520f5d-... isError=true model=claude-opus-4-6 provider=anthropic error=LLM request rejected: You're out of extra usage. Add more at claude.ai/settings/usage and keep going.
[agent] auth profile failure state updated: runId=e8520f5d-... profile=sha256:154a23a3efe6 provider=anthropic reason=billing window=disabled

# All subsequent failures: cooldown skip message, isBillingErrorMessage() does NOT match:
[model-fallback] model fallback decision: decision=skip_candidate requested=anthropic/claude-opus-4-6 candidate=anthropic/claude-opus-4-6 reason=billing next=anthropic/claude-sonnet-4-6 detail=Provider anthropic has billing issue (skipping all models)
[model-fallback] model fallback decision: decision=skip_candidate requested=anthropic/claude-opus-4-6 candidate=anthropic/claude-sonnet-4-6 reason=billing next=none detail=Provider anthropic has billing issue (skipping all models)
Embedded agent failed before reply: All models failed (2): anthropic/claude-opus-4-6: Provider anthropic has billing issue (skipping all models) (billing) | anthropic/claude-sonnet-4-6:
Provider anthropic has billing issue (skipping all models) (billing)

# This pattern repeats every 30 minutes for hours:
2026-04-13T22:41:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-13T23:11:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-13T23:41:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-14T00:11:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-14T00:41:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)
2026-04-14T01:11:05 ... Embedded agent failed before reply: All models failed (2): ... (billing) | ... (billing)

Impact and severity

  • Affected: All OAuth-authenticated users who exhaust their personal Anthropic usage quota; also affects API key setups that run out of credits
  • Severity: Medium: misleading error message, users cannot diagnose the billing issue unless read logs
  • Frequency: Always reproduces after the first billing failure triggers cooldown; common with OAuth since personal usage caps are hit more frequently
  • Consequence: Users see "Something went wrong" with no actionable guidance (e.g. "top up at claude.ai/settings/usage"), repeatedly retry without understanding the root cause

Additional information

Root cause: agent-runner-execution.ts checks isBillingErrorMessage(message) but FallbackSummaryError messages from the billing cooldown skip path contain "has billing issue" which matches none of the patterns in failover-matches.ts ERROR_PATTERNS.billing.

The rate-limit path already handles this correctly via isPureTransientRateLimitSummary() which checks the structured attempt.reason field instead of string-matching. The billing path lacks an equivalent check.

The OAuth path makes this especially common for personal "extra usage" quotas on claude.ai are generally smaller than typical org API budgets, so users hit this more frequently. The Anthropic error is: 400 {"type":"error","error":{"type":"invalid_request_error","message":"You're out of extra usage. Add more at claude.ai/settings/usage and keep going."}}

Related issues: #48526, #64224, #64308, #62375 Related PR (partial fix): #61608 added "out of extra usage" pattern but only for raw API errors, not cooldown-generated messages.

First appeared in Friends of the Crustacean discord server on ~7 April 2026. [1]

extent analysis

TL;DR

The issue can be fixed by modifying the isBillingErrorMessage() function to correctly match the "has billing issue" message or by adding a check for the structured attempt.reason field.

Guidance

  • Modify the isBillingErrorMessage() function in failover-matches.ts to include a pattern that matches the "has billing issue" message.
  • Add a check for the structured attempt.reason field in the billing path, similar to the rate-limit path, to correctly identify billing errors.
  • Update the ERROR_PATTERNS.billing array to include the new pattern.
  • Verify that the fix works by testing the scenario with an exhausted personal "extra usage" quota and checking that the correct error message is displayed.

Example

// In failover-matches.ts
const ERROR_PATTERNS = {
  // ...
  billing: [
    // ...
    'has billing issue', // Add this pattern
  ],
};

// In agent-runner-execution.ts
if (attempt.reason === 'billing' || isBillingErrorMessage(message)) {
  // Handle billing error
}

Notes

The fix may not work if the "has billing issue" message is not the only message that can be returned by the Anthropic API. Additional error messages may need to be handled.

Recommendation

Apply the workaround by modifying the isBillingErrorMessage() function and adding a check for the structured attempt.reason field. This will correctly handle the billing error and display the correct error message to the user.

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

On subsequent failures after billing cooldown kicks in, users should see BILLING_ERROR_USER_MESSAGE: "⚠️ API provider returned a billing error — your API key has run out of credits or has an insufficient balance. Check your provider's billing dashboard and top up or switch to a different API key."

Still need to ship something?

×6

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

Back to top recommendations

TRENDING