mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix(providers): classify 404 as MODEL_NOT_FOUND to stop retry storm (#6829)
Reconstructed onto release/v3.8.47 to drop unrelated main-drift (deps/electron/proxy files belong to #6620, not this PR) and the direct CHANGELOG.md edit (fragments-first); the author's chatCore/errorClassifier deltas were re-applied cleanly onto the release tip. Co-authored-by: Andrian B. <andrewbalanesq@gmail.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
1
changelog.d/fixes/6829-classify-404-model-not-found.md
Normal file
1
changelog.d/fixes/6829-classify-404-model-not-found.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(providers):** classify upstream `404` responses as `MODEL_NOT_FOUND` (model lockout) instead of a retryable provider error, stopping the retry storm when a single model is missing (#6829 — thanks @AndrianBalanescu).
|
||||
@@ -3306,6 +3306,16 @@ export async function handleChatCore({
|
||||
console.warn(
|
||||
`[provider] Node ${errorConnectionId} project routing error (${statusCode}) — not banning`
|
||||
);
|
||||
} else if (errorType === PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND) {
|
||||
// 404 — model/endpoint does not exist upstream. Lock the model so the
|
||||
// retry/backoff loop stops hammering the dead endpoint (which would
|
||||
// otherwise degenerate into a 429 rate-limit storm). Connection stays
|
||||
// active since only the specific model is unavailable. (#6827)
|
||||
const notFoundCooldownMs = COOLDOWN_MS.notFound;
|
||||
lockModel(provider, errorConnectionId, currentModel, "model_not_found", notFoundCooldownMs);
|
||||
console.warn(
|
||||
`[provider] Node ${errorConnectionId} model not found (${statusCode}) for ${currentModel} - locking model for ${Math.ceil(notFoundCooldownMs / 1000)}s (connection stays active)`
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
// Best-effort state update; request flow should continue with fallback handling.
|
||||
|
||||
@@ -76,6 +76,7 @@ export const PROVIDER_ERROR_TYPES = {
|
||||
CONTEXT_OVERFLOW: "context_overflow",
|
||||
OAUTH_INVALID_TOKEN: "oauth_invalid_token",
|
||||
EMPTY_CONTENT: "empty_content",
|
||||
MODEL_NOT_FOUND: "model_not_found",
|
||||
};
|
||||
|
||||
export const CONTEXT_OVERFLOW_SIGNALS = [
|
||||
@@ -144,6 +145,15 @@ export function classifyProviderError(
|
||||
return PROVIDER_ERROR_TYPES.RATE_LIMITED;
|
||||
}
|
||||
|
||||
// 404 — model or endpoint not found. Without classification the error
|
||||
// falls through to `return null`, so no cooldown/lockout is applied and the
|
||||
// retry/backoff loop keeps hammering the dead endpoint until the upstream
|
||||
// rate-limits it (404 + 429 storm). Classify as MODEL_NOT_FOUND so the model
|
||||
// gets locked via the cooldown layer and retries stop. (#6827)
|
||||
if (statusCode === 404) {
|
||||
return PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (statusCode === 401) {
|
||||
if (oauthInvalid) {
|
||||
return PROVIDER_ERROR_TYPES.OAUTH_INVALID_TOKEN;
|
||||
|
||||
@@ -120,3 +120,22 @@ test("classifyProviderError: OAuth provider 429 with daily quota signal => QUOTA
|
||||
);
|
||||
assert.equal(result, PROVIDER_ERROR_TYPES.QUOTA_EXHAUSTED);
|
||||
});
|
||||
|
||||
// #6827 — 404 must be classified as MODEL_NOT_FOUND, not fall through to null.
|
||||
// Without this, no cooldown/lockout is applied and the retry loop keeps hitting
|
||||
// the dead endpoint until the upstream rate-limits it (404 + 429 storm).
|
||||
test("classifyProviderError: 404 => MODEL_NOT_FOUND", () => {
|
||||
const result = classifyProviderError(404, {
|
||||
error: { message: "model v0-1.5-md not found" },
|
||||
});
|
||||
assert.equal(result, PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND);
|
||||
});
|
||||
|
||||
test("classifyProviderError: 404 with provider => MODEL_NOT_FOUND", () => {
|
||||
const result = classifyProviderError(
|
||||
404,
|
||||
{ error: { message: "Not Found" } },
|
||||
"v0-vercel"
|
||||
);
|
||||
assert.equal(result, PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user