fix(auxiliary): treat OpenRouter 403 key/spend-limit errors as payment exhaustion for fallback#13903
Open
HiddenPuppy wants to merge 4 commits into
Open
fix(auxiliary): treat OpenRouter 403 key/spend-limit errors as payment exhaustion for fallback#13903HiddenPuppy wants to merge 4 commits into
HiddenPuppy wants to merge 4 commits into
Conversation
added 4 commits
April 22, 2026 15:18
…call messages for Kimi /coding Fixes NousResearch#13848 Kimi's /coding endpoint speaks the Anthropic Messages protocol but has its own thinking semantics: when thinking is enabled, Kimi validates message history and requires every prior assistant tool-call message to carry OpenAI-style reasoning_content. The Anthropic path never populated that field, and convert_messages_to_anthropic strips all Anthropic thinking blocks on third-party endpoints — so the request failed with HTTP 400: "thinking is enabled but reasoning_content is missing in assistant tool call message at index N" Now, when an assistant message contains tool_calls and a reasoning_content string, we append a {"type": "thinking", ...} block to the Anthropic content so Kimi can validate the history. This only affects assistant messages with tool_calls + reasoning_content; plain text assistant messages are unchanged.
Map tsuijinglei@gmail.com → hiddenpuppy.
…t exhaustion for fallback Fixes NousResearch#13887 OpenRouter returns HTTP 403 (not 402) for key-limit and spend-limit errors. The existing _is_payment_error() only checked 402/429/None, so these 403s were not classified as payment exhaustion and auxiliary calls would fail immediately instead of falling back to the next provider. Now _is_payment_error() also checks status == 403 and looks for OpenRouter-specific keywords: key limit, spending limit, spend limit, total limit, credit limit, quota exceeded. This keeps the fix scoped: only 403s with these specific phrases are treated as payment errors. Other 403s (auth, forbidden, etc.) still raise normally. The fallback path already skips the failed provider via _try_payment_fallback(), so no changes are needed there.
Map jerome@clawwork.ai → HiddenPuppy.
Contributor
|
I believe the original issue is not valid, see #13887 (comment) Perhaps a new one can be created if this PR is to be reviewed. |
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
Fixes #13887
Problem
When auxiliary tasks run with
provider=auto, OpenRouter returns HTTP 403 for key-limit and spend-limit errors. The existing_is_payment_error()only checked for HTTP 402/429/None, so these 403s were not classified as payment exhaustion. Auxiliary calls would fail immediately instead of falling back to the next available provider (Codex OAuth, Nous, custom endpoint, etc.).Screenshot in the issue shows 3 retries with the same model and same error instead of trying a fallback provider.
Root Cause
_is_payment_error()was too narrow — missing OpenRouter 403 key-limit/spend-limit wording_try_payment_fallback()) works correctly but was never reached because the error wasn't classified as payment-relatedFix
Extend
_is_payment_error()to also check HTTP 403 responses for OpenRouter-specific payment exhaustion keywords:"key limit""spending limit"/"spend limit""total limit""credit limit""quota exceeded"This is intentionally scoped — only 403s with these specific phrases are treated as payment errors. Other 403s (auth, forbidden, etc.) still raise normally.
Changes
agent/auxiliary_client.py:_is_payment_error()— added 403 + keyword checkVerification
pytestpassesChecklist