← Back to PRs

#16529: fix(fallback): treat OpenRouter routing errors as failover-eligible

by zirubak open 2026-02-14 20:50 View on GitHub →
agents stale size: XS
## Summary - When using `openrouter/auto`, if the auto router picks a model that doesn't support image input, OpenRouter returns a `404 No endpoints found that support image input` error - This 404 error was **not** classified as failover-eligible, so the fallback model chain was never tried — the error was thrown immediately - Added "no endpoints found" as a recognized routing error pattern that triggers model fallback (classified as `format` reason) - Now when this error happens, OpenClaw will automatically try the next model in the fallback list (e.g., a vision-capable model like `gemini-3-flash`) ## Changes | File | What changed | |------|-------------| | `src/agents/pi-embedded-helpers/errors.ts` | Added `ERROR_PATTERNS.routing` with "no endpoints found" patterns, added `isRoutingErrorMessage()`, added routing check to `classifyFailoverReason()` | | `src/agents/pi-embedded-helpers.ts` | Exported `isRoutingErrorMessage` | | `src/agents/pi-embedded-helpers.classifyfailoverreason.e2e.test.ts` | Added 4 test cases for routing error classification | ## How it works **Before:** `openrouter/auto` fails with 404 → error thrown → user sees error message **After:** `openrouter/auto` fails with 404 → classified as `format` failover → tries next model in fallback list → works with a vision-capable fallback model ## Test plan - [x] All 3 new routing error test cases pass - [x] All 20 existing model-fallback tests pass - [x] Full unit test suite passes (6045 tests, 911 files) - [ ] Manual test: send an image via Telegram with `openrouter/auto` as primary model and verify fallback triggers instead of 404 error <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds OpenRouter routing errors (e.g., "No endpoints found that support image input") as failover-eligible, classified under the `format` reason. This allows the fallback model chain to engage when `openrouter/auto` selects a model that doesn't support the request's input modality (e.g., images). - Added `ERROR_PATTERNS.routing` with a string pattern and regex for "no endpoints found" variants - Added `isRoutingErrorMessage()` helper and exported it from the barrel file - Integrated the routing check into `classifyFailoverReason()` after all other checks, returning `"format"` reason - Added a test case covering four error message variants (with HTTP prefix, plain text, JSON-wrapped, and lowercase) The placement of the routing check at the end of `classifyFailoverReason()` is correct — no earlier check would false-positive on these messages. The change integrates cleanly with the existing `resolveFailoverReasonFromError` path in `failover-error.ts`, since HTTP 404 status codes don't match any explicit status-code branches and correctly fall through to message-based classification. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it adds a well-scoped error classification pattern with no risk to existing behavior. - The change is minimal and focused: it adds a new error pattern category and integrates it into the existing classification chain. The routing check is correctly ordered after all other checks in classifyFailoverReason(), avoiding false positives. The "no endpoints found" pattern is specific to OpenRouter routing errors and won't match other error types. All existing tests continue to pass, and the new test covers four representative error message formats. The regex and string patterns are consistent with established patterns in the codebase. - No files require special attention. <sub>Last reviewed commit: 3c0a085</sub> <!-- greptile_other_comments_section --> <sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs