fix(agent): classify Anthropic "extra usage" 400 as billing, not format_error - #49379
Closed
aldoeliacim wants to merge 1 commit into
Closed
fix(agent): classify Anthropic "extra usage" 400 as billing, not format_error#49379aldoeliacim wants to merge 1 commit into
aldoeliacim wants to merge 1 commit into
Conversation
aldoeliacim
force-pushed
the
fix/anthropic-extra-usage-400-billing
branch
3 times, most recently
from
July 1, 2026 20:44
6bc8ecf to
1a83bfc
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates Hermes’ API error classification to recognize Anthropic “extra usage” entitlement errors that arrive as HTTP 400 and route them to the billing failover bucket (instead of format_error), enabling correct user guidance and credential rotation behavior.
Changes:
- Add
_ENTITLEMENT_PATTERNSand classify matching Anthropic 400 errors asFailoverReason.billing(non-retryable, rotate credential, allow fallback). - Extend the no-status message-only classifier to also treat these entitlement messages as
billing, while explicitly avoiding collision with the 429 long-context tier gate. - Add a focused test suite covering entitlement phrasings and the “no collision” invariant with the existing 429
long_context_tierbehavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
agent/error_classifier.py |
Adds entitlement-specific pattern matching to classify certain Anthropic 400s (and message-only cases) as billing. |
tests/agent/test_entitlement_extra_usage_classification.py |
Adds regression tests for entitlement message classification and guards against misclassifying the 429 long-context tier gate. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
aldoeliacim
force-pushed
the
fix/anthropic-extra-usage-400-billing
branch
from
July 3, 2026 00:15
1a83bfc to
2881e94
Compare
aldoeliacim
force-pushed
the
fix/anthropic-extra-usage-400-billing
branch
from
July 4, 2026 19:58
2881e94 to
73f7bd5
Compare
…at_error
When a Claude subscription must enable extra usage to keep serving, native
Anthropic returns HTTP 400 with a body like "Third-party apps now draw from
your extra usage. To continue, enable extra usage in your account settings."
The generic 400 path classified this as format_error, so:
- the user saw an opaque "format error" instead of the actionable
billing/entitlement guidance, and
- no credential rotation was triggered (should_rotate_credential stayed
False), so a multi-credential pool never rotated to another entry.
Add a dedicated _ENTITLEMENT_PATTERNS list and classify these messages as
FailoverReason.billing (retryable=False, should_rotate_credential=True,
should_fallback=True) in both the 400-status path and the no-status message
path. Patterns are specific to an account *action* on extra usage so they do
NOT collide with the 429 rolling-cap / long-context tier gate ("extra usage" +
"long context"), which stays long_context_tier; the no-status path also guards
on "long context" explicitly.
Tests: entitlement variants -> billing + rotate; long-context tier stays
long_context_tier; real credit-balance billing unchanged. Full classifier
suite (161) green.
aldoeliacim
force-pushed
the
fix/anthropic-extra-usage-400-billing
branch
from
July 4, 2026 21:37
73f7bd5 to
7c16dd3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
When a Claude subscription must enable extra usage to keep serving, native Anthropic returns HTTP 400 with a body like:
_classify_400had no pattern for this, so it fell through to the genericformat_errorbucket. Two real consequences:_print_billing_or_entitlement_guidance).billingsetsshould_rotate_credential=True;format_errordoes not. A multi-credential pool never rotates to another entry on this signal.Both
_classify_400(status path) and_classify_by_message(no-status sibling path) are fixed, so the whole class is covered rather than one call site.The fix
Add a dedicated
_ENTITLEMENT_PATTERNSlist and classify these messages asFailoverReason.billing(retryable=False,should_rotate_credential=True,should_fallback=True).Patterns are deliberately specific to an account action on extra usage (
draw from your extra usage,enable extra usage,exceed your extra usage,extra usage allowance) so they do not collide with the existing 429 rolling-cap / long-context tier gate ("extra usage"+"long context"→long_context_tier, retryable). The no-status path additionally guards on"long context"explicitly.How to test
New test
tests/agent/test_entitlement_extra_usage_classification.pycovers:billing+ rotate + fallbackextra usage+long contextstayslong_context_tiercredit balancebilling stillbillingtests/agent/test_error_classifier.py(161 tests) stays green.Platforms
Logic-only change in
agent/error_classifier.py(string matching + classification flags); no OS-specific paths. Tested on Linux.Rebased onto current
main(2026-06-26). Conflict inagent/error_classifier.py: main added an_OVERLOADED_PATTERNSblock at the same no-status classification point; resolved by ordering overloaded → entitlement → generic billing so the transient-overload check runs first and the specific entitlement match still wins over generic_BILLING_PATTERNS. Verified:test_error_classifier+ entitlement + failover = 180 passed.