Skip to content

fix: skip disabled providers in combo fallback - #336

Merged
decolua merged 1 commit into
decolua:masterfrom
East-rayyy:fix/skip-disabled-providers-in-combo
Mar 23, 2026
Merged

decolua merged 1 commit into
decolua:masterfrom
East-rayyy:fix/skip-disabled-providers-in-combo

Conversation

@East-rayyy

@East-rayyy East-rayyy commented Mar 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • When a combo model includes a provider with only disabled credentials, return 404 (fallbackable) instead of 400 (hard error), so the combo handler skips to the next model
  • Changed log level from error to warn since disabled credentials are an expected state

Fixes #334
Fixes #164
Fixes #25

Problem

A combo like antigravity/opus → github/opus would fail with 406: No credentials for provider: github when GitHub credentials were disabled. The 400 status from handleSingleModelChat was treated as non-fallbackable by the combo handler, killing the client.

Change

1 file, 2 lines changed — src/sse/handlers/chat.js

HTTP_STATUS.BAD_REQUEST → HTTP_STATUS.NOT_FOUND for the "no credentials" case when no connections have been tried yet. checkFallbackError already handles NOT_FOUND as fallbackable with a notFound cooldown.

Test plan

  • Create a combo with a provider that has all credentials disabled
  • Verify the combo skips the disabled provider and tries the next model
  • Verify providers with no credentials at all also get skipped
  • Verify providers with active credentials still work normally

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
East-rayyy force-pushed the fix/skip-disabled-providers-in-combo branch from 1cdbd75 to 4139e5a Compare March 18, 2026 07:35
@decolua
decolua merged commit 037d013 into decolua:master Mar 23, 2026
@East-rayyy
East-rayyy deleted the fix/skip-disabled-providers-in-combo branch March 23, 2026 15:39
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>
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.

Combo fallback returns 406 when provider has only disabled credentials combo fallback lỗi API Error:400 github copilot

2 participants