fix(auth): classify permission_error as auth_permanent for profile fallback#31324
Merged
vincentkoc merged 3 commits intoopenclaw:mainfrom Mar 2, 2026
Merged
Conversation
…llback When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor
Contributor
Greptile SummaryThis PR fixes a critical failover bug where OAuth profiles returning HTTP 403 with The fix adds two specific error patterns to the
These patterns now trigger the same exponential backoff as billing errors (via Key changes:
Impact:
Confidence Score: 5/5
Last reviewed commit: 571d29f |
18 tasks
robertchang-ga
pushed a commit
to robertchang-ga/openclaw
that referenced
this pull request
Mar 2, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
hanqizheng
pushed a commit
to hanqizheng/openclaw
that referenced
this pull request
Mar 2, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
execute008
pushed a commit
to execute008/openclaw
that referenced
this pull request
Mar 2, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
dawi369
pushed a commit
to dawi369/davis
that referenced
this pull request
Mar 3, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
OWALabuy
pushed a commit
to kcinzgg/openclaw
that referenced
this pull request
Mar 4, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
sachinkundu
pushed a commit
to sachinkundu/openclaw
that referenced
this pull request
Mar 6, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
zooqueen
pushed a commit
to hanzoai/bot
that referenced
this pull request
Mar 6, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
atlastacticalbot
pushed a commit
to tensakulabs/atlasbot
that referenced
this pull request
Mar 6, 2026
…llback (openclaw#31324) When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes openclaw#31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commit 40e078a)
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.
Summary
permission_error(e.g. expired organization plan), the error is classified as genericauthinstead ofauth_permanent. Theauthclassification applies only a short cooldown, so the gateway keeps retrying the same broken profile indefinitely (20+ consecutive 403s observed)."permission_error"and"not allowed for this organization"to theauthPermanenterror patterns inERROR_PATTERNS. This causes these errors to receive the longerdisabledUntilbackoff window (same treatment as revoked keys and billing errors), enabling proper rotation to the next healthy profile.resolveFailoverReasonFromErrorfunction already returnsauthfor 403 status codes — this change makes it returnauth_permanentwhen the error message containspermission_error. Regular 403s withoutpermission_errorstill classify asauth.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
permission_errorare now placed into a longer disable window (exponential backoff) instead of a short cooldown.lastGoodis cleared for the failing profile, preventing immediate re-selection.Security Impact (required)
NoNoNoNoNoRepro + Verification
Environment
Steps
anthropic:100(token, valid) andanthropic:200(OAuth, expired plan)lastGood.anthropicpoint toanthropic:200Expected
:200, gets 403permission_error, classifies asauth_permanent, disables profile, rotates to:100Actual
:200with short cooldown, never effectively rotating:200with exponential backoff and rotates to:100Evidence
Three new test cases in
failover-error.test.ts:403 permission_error returns auth_permanent(via status + message)permission_error in error message string classifies as auth_permanent(via coercion)"not allowed for this organization" classifies as auth_permanentHuman Verification (required)
authauthPermanentpatterns still work (revoked key, invalid_api_key, deactivated account)Compatibility / Migration
Yes— only changes classification of a previously under-handled errorNoNoFailure Recovery (if this breaks)
"permission_error"and"not allowed for this organization"fromauthPermanentpatterns insrc/agents/pi-embedded-helpers/errors.tssrc/agents/pi-embedded-helpers/errors.tsRisks and Mitigations
permission_erroris a specific Anthropic error type for org-level permission issues, not transient API errors. Adding the more specific"not allowed for this organization"string narrows the match. Generic 403s still classify asauth(shorter cooldown).