Repository navigation
fix: skip disabled providers in combo fallback - #336
Merged
decolua merged 1 commit intoMar 23, 2026
Merged
Conversation
When a provider has credentials but all are disabled, return 404 (NOT_FOUND) instead of 400 (BAD_REQUEST). The combo handler already treats 404 as a fallbackable error, so it will skip to the next model in the chain. Previously, the 400 status caused the combo to stop with a hard error, killing the client (e.g., Claude Code) even though other models in the combo chain were available. Also changed log level from error to warn since disabled credentials are an expected configuration state, not an error. Fixes #334
East-rayyy
force-pushed
the
fix/skip-disabled-providers-in-combo
branch
from
March 18, 2026 07:35
1cdbd75 to
4139e5a
Compare
This was referenced Mar 18, 2026
Closed
idbara
pushed a commit
to idbara/9router
that referenced
this pull request
Apr 23, 2026
…06 (decolua#336) When a provider has credentials but all are disabled, return 404 (NOT_FOUND) instead of 400 (BAD_REQUEST). The combo handler already treats 404 as a fallbackable error, so it will skip to the next model in the chain. Previously, the 400 status caused the combo to stop with a hard error, killing the client (e.g., Claude Code) even though other models in the combo chain were available. Also changed log level from error to warn since disabled credentials are an expected configuration state, not an error. Fixes decolua#334
luckystart79-lang
pushed a commit
to luckystart79-lang/minirouter
that referenced
this pull request
May 2, 2026
…06 (decolua#336) When a provider has credentials but all are disabled, return 404 (NOT_FOUND) instead of 400 (BAD_REQUEST). The combo handler already treats 404 as a fallbackable error, so it will skip to the next model in the chain. Previously, the 400 status caused the combo to stop with a hard error, killing the client (e.g., Claude Code) even though other models in the combo chain were available. Also changed log level from error to warn since disabled credentials are an expected configuration state, not an error. Fixes decolua#334
caothu159
pushed a commit
to diepxuan/9router
that referenced
this pull request
May 14, 2026
…06 (decolua#336) When a provider has credentials but all are disabled, return 404 (NOT_FOUND) instead of 400 (BAD_REQUEST). The combo handler already treats 404 as a fallbackable error, so it will skip to the next model in the chain. Previously, the 400 status caused the combo to stop with a hard error, killing the client (e.g., Claude Code) even though other models in the combo chain were available. Also changed log level from error to warn since disabled credentials are an expected configuration state, not an error. Fixes decolua#334
diegosouzapw
pushed a commit
to diegosouzapw/OmniRoute
that referenced
this pull request
Jun 21, 2026
When a combo target (e.g. `antigravity/opus → github/opus`) hit a leg whose only configured connections were disabled, `handleNoCredentials` in `src/sse/handlers/chatHelpers.ts` returned 400 BAD_REQUEST. The combo target loop treats 400 as a hard stop — added by PR #4316 / issue #4279 to prevent infinite fallback loops on body-specific 4xx errors — so the combo died on the first leg even when the next target was perfectly healthy. The "no usable credentials, no connections tried yet" branch now returns 404 NOT_FOUND with the message "No active credentials for provider: <p>" instead. 404 flows through `checkFallbackError` as `shouldFallback: true` via the generic-error catch-all path in `open-sse/services/accountFallback.ts` (no explicit 404 special-case + transient cooldown), so the combo loop tries the next target. The log level for this branch also drops from `error` to `warn` because zero active credentials is an expected operator-driven state, not a server fault. The sibling branches in `handleNoCredentials` were left untouched: - `allRateLimited` already returns the upstream status (combo-fallbackable). - `allExpired` already returns 401 with a reconnect hint (combo-fallbackable via `checkFallbackError`). - The post-exhaustion branch (after at least one connection tried) already preserves `lastStatus`. Tests updated to encode the new contract (TDD: failing-then-passing per Hard Rule #18): `chat-helpers`, `chat-route-coverage`, `vscode-token-routes`, `chat-pipeline`, `llama-cpp-provider`, `combo-routing-e2e`. The `vscode-token-routes` assertions also flip `error.code` from `bad_request` to `model_not_found` per the OpenAI-compatible status mapping in `open-sse/config/errorConfig.ts:29`. Routes that emit `400 No credentials for provider` directly (rerank, audio, moderations, image edits, embeddings) are untouched — they don't flow through combo, so the 400 hard-stop semantics don't apply. Inspired-by upstream decolua/9router#336 (Ibrahim Ryan). Co-authored-by: Ibrahim Ryan <ryan@nuevanext.com>
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
404(fallbackable) instead of400(hard error), so the combo handler skips to the next modelerrortowarnsince disabled credentials are an expected stateFixes #334
Fixes #164
Fixes #25
Problem
A combo like
antigravity/opus → github/opuswould fail with406: No credentials for provider: githubwhen GitHub credentials were disabled. The400status fromhandleSingleModelChatwas treated as non-fallbackable by the combo handler, killing the client.Change
1 file, 2 lines changed —
src/sse/handlers/chat.jsHTTP_STATUS.BAD_REQUEST→HTTP_STATUS.NOT_FOUNDfor the "no credentials" case when no connections have been tried yet.checkFallbackErroralready handlesNOT_FOUNDas fallbackable with anotFoundcooldown.Test plan