Skip to content

fix(core): classify Claude usage-limit errors as rate limits#1761

Open
k4n4lm00n wants to merge 1 commit into
coleam00:devfrom
k4n4lm00n:fix/usage-limit-errors
Open

fix(core): classify Claude usage-limit errors as rate limits#1761
k4n4lm00n wants to merge 1 commit into
coleam00:devfrom
k4n4lm00n:fix/usage-limit-errors

Conversation

@k4n4lm00n
Copy link
Copy Markdown

@k4n4lm00n k4n4lm00n commented May 25, 2026

Summary

  • Problem: Claude's 5-hour usage cap surfaced to users as a generic "⚠️ An unexpected error occurred. Try /reset…".
  • Why it matters: On chat surfaces the bot's reply is the only error signal — an opaque message looks like a crash and invites pointless /reset attempts, when the user just needs to wait for the reset.
  • What changed: classifyAndFormatError (core) now recognises Claude usage-cap phrasings and surfaces a clear message with the reset time. Applies to every platform.
  • What did NOT change (scope boundary): Only error-formatter.ts (+ its tests). No provider, adapter, workflow, or schema changes.

Provenance

Proudly built with and by Archon and Claude Code, with a pinch of human experience steering the wheel. 🤖🧂

Why this is needed

Archon speaks to users through chat (Zulip, Slack, Telegram, …) where there are no logs to open — the bot's reply is the entire error surface. classifyAndFormatError is the single place that turns raw provider/SDK errors into human guidance, and it already does this for several cases: e.g. an expired Claude auth/OAuth token becomes "⚠️ Claude authentication expired. Run /login …" instead of an opaque failure, telling the user exactly how to recover.

The gap this PR closes sits right next to that case. Claude's 5-hour usage cap surfaces as "You've hit your limit · resets <time>" (and "usage limit" when org overage is disabled). None of those phrasings matched the existing rate-limit branch, so they fell through to the catch-all "⚠️ An unexpected error occurred. Try /reset…" — which reads like a crash and triggers /reset attempts that cannot help. We now match those phrasings (case-insensitively) alongside "rate limit" and echo the reset time.

UX Journey

Before

[on a Claude usage cap, any platform]
send message ───────────▶  AI query rejected (usage cap)
sees "⚠️ An unexpected     ◀── generic fallback (no cause, no reset time)
 error occurred."

After

send message ───────────▶  AI query rejected (usage cap)
sees "⚠️ AI usage limit     ◀── classified message w/ reset time
 reached (resets 4:50pm
 (UTC)). Please wait…"

Label Snapshot

  • Risk: risk: low
  • Size: size: XS
  • Scope: core
  • Module: core:error-formatter

Change Metadata

  • Change type: bug
  • Primary scope: core

Linked Issue

  • No linked GitHub issue.

Validation Evidence (required)

bun run type-check    # all packages exit 0
bun run lint          # eslint --cache, 0 warnings/errors
bun run format:check  # all files match Prettier
bun test packages/core/src/utils/error-formatter.test.ts  # 57 pass, 0 fail (100% coverage of error-formatter.ts)

Security Impact (required)

  • New permissions/capabilities? No.
  • New external network calls? No.
  • Secrets/tokens handling changed? No.
  • File system access scope changed? No.

Compatibility / Migration

  • Backward compatible? Yes — only improves an error message's wording.
  • Config/env changes? No.
  • Database migration needed? No.

Human Verification (required)

  • Verified: fed Claude's real error string through classifyAndFormatError⚠️ AI usage limit reached (resets 4:50pm (UTC)). Please wait and try again.; generic/unrelated errors still fall through unchanged.
  • What was not verified: a real production cap end-to-end (the classification path is confirmed; awaiting the next actual cap to observe it live).

Side Effects / Blast Radius (required)

  • Affected subsystems: core error formatting — the new message shows on all platforms.
  • Potential unintended effects: could re-classify any error text containing "hit your limit" / "usage limit"; low risk since only AI-provider errors reach this function.
  • Guardrails/monitoring: error-formatter.ts at 100% test coverage (57 cases).

Rollback Plan (required)

  • Fast rollback: revert the single commit.
  • Observable failure symptoms: usage-cap errors revert to the generic "unexpected error" message.

Risks and Mitigations

  • Risk: false positives on unrelated error text.
    • Mitigation: only provider errors reach the function; behavior locked down by tests.

Summary by CodeRabbit

Bug Fixes

  • Enhanced error messages for rate limiting and usage limit conditions to be more informative and user-friendly, now detecting multiple limit error types and including reset timing information when available to help users understand service availability better.

Review Change Stack

Claude's 5-hour subscription cap surfaces as "You've hit your limit ·
resets <time>" (and "usage limit" when org overage is disabled). Neither
matched the rate-limit branch in classifyAndFormatError, so users hit the
generic "An unexpected error occurred" fallback instead of a clear message.

Match both phrasings case-insensitively alongside "rate limit" and echo the
reset time when present, e.g. "⚠️ AI usage limit reached (resets 4:50pm
(UTC)). Please wait and try again." Applies to every platform.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0f3cddf4-6ad7-4d15-96d7-d3ef34f77f0c

📥 Commits

Reviewing files that changed from the base of the PR and between c903c79 and c5f460d.

📒 Files selected for processing (2)
  • packages/core/src/utils/error-formatter.test.ts
  • packages/core/src/utils/error-formatter.ts

📝 Walkthrough

Walkthrough

Error classification for rate and usage limits now detects multiple phrases with case-insensitive matching and extracts optional reset timestamps from error messages. Test suite expanded to cover Claude subscription limits, reset-time variants, and abbreviated time formatting.

Changes

Rate Limit Error Handling

Layer / File(s) Summary
Rate limit classification with reset time extraction
packages/core/src/utils/error-formatter.ts
classifyAndFormatError now uses case-insensitive matching for multiple phrases ("rate limit", "hit your limit", "usage limit") and parses optional reset timestamps anchored on "· resets …" to include in returned user-facing warnings.
Test coverage for rate limit detection and reset time parsing
packages/core/src/utils/error-formatter.test.ts
Rate limit test suite updated to expect new usage-limit message text and expanded with test cases for Claude "hit your limit" variants, reset-time parsing with abbreviated formatting (e.g., p.m.), and priority ordering precedence validation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • coleam00/Archon#1089: Both PRs modify error classification logic in classifyAndFormatError, updating conditional branching for error precedence and message formatting.

Poem

🐰 A bunny hops through error codes with glee,
Finding rate limits hidden in the spree,
Now reset times bloom like clover spring—
Users see the countdown, clarity they bring! 🕐

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: classifying Claude usage-limit errors as rate limits in the core error formatter.
Description check ✅ Passed The description comprehensively covers all required template sections: Summary, UX Journey (Before/After), Labels, Change Metadata, Linked Issues, Validation Evidence, Security Impact, Compatibility, Human Verification, Side Effects, Rollback Plan, and Risks with Mitigations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant