mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 06:42:12 +03:00
fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model (#8319)
This commit is contained in:
committed by
GitHub
parent
ddbd054e49
commit
dcbea8eb0d
1
changelog.d/fixes/8136-antigravity-400-lockout.md
Normal file
1
changelog.d/fixes/8136-antigravity-400-lockout.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(providers): classify HTTP 400 model-unavailable as MODEL_NOT_FOUND so Antigravity Pro fallback locks out the deprecated model
|
||||
@@ -232,8 +232,18 @@ export function classifyProviderError(
|
||||
}
|
||||
if (statusCode >= 500) return PROVIDER_ERROR_TYPES.SERVER_ERROR;
|
||||
|
||||
if (statusCode === 400 && isContextOverflow(bodyStr)) {
|
||||
return PROVIDER_ERROR_TYPES.CONTEXT_OVERFLOW;
|
||||
if (statusCode === 400) {
|
||||
if (isContextOverflow(bodyStr)) {
|
||||
return PROVIDER_ERROR_TYPES.CONTEXT_OVERFLOW;
|
||||
}
|
||||
// Some providers (e.g. Antigravity's Pro-fallback chain, #8136) return a
|
||||
// plain 400 for a model that is no longer available, instead of 404/401.
|
||||
// Without this check the error falls through to `return null`, so
|
||||
// lockModel() never fires and the same dead model gets retried on every
|
||||
// request. Detect the phrasing here, same as the 401 branch above (#7268).
|
||||
if (containsModelUnavailableMessage(bodyStr)) {
|
||||
return PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
const { classifyProviderError, PROVIDER_ERROR_TYPES } = await import(
|
||||
"../../open-sse/services/errorClassifier.ts"
|
||||
);
|
||||
|
||||
test("#8136: classifyProviderError(400, Antigravity 'model is not supported' body) returns MODEL_NOT_FOUND", () => {
|
||||
const body = {
|
||||
error: {
|
||||
code: 400,
|
||||
message: "The model gemini-3.1-pro-low is not supported for this project.",
|
||||
status: "INVALID_ARGUMENT",
|
||||
},
|
||||
};
|
||||
const classified = classifyProviderError(400, body, "antigravity");
|
||||
assert.equal(
|
||||
classified,
|
||||
PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND,
|
||||
`expected MODEL_NOT_FOUND, got ${JSON.stringify(classified)}`
|
||||
);
|
||||
});
|
||||
|
||||
test("#8136: same phrasing at 401 still works (regression guard for #7268)", () => {
|
||||
const body = { error: { message: "The model gemini-3.1-pro-low is not supported for this project." } };
|
||||
assert.equal(classifyProviderError(401, body, "antigravity"), PROVIDER_ERROR_TYPES.MODEL_NOT_FOUND);
|
||||
});
|
||||
|
||||
test("#8136: plain 400 context-overflow still classifies as CONTEXT_OVERFLOW, not MODEL_NOT_FOUND", () => {
|
||||
const body = {
|
||||
error: {
|
||||
message: "This model's maximum context length is 128000 tokens. Please reduce the length of the messages.",
|
||||
},
|
||||
};
|
||||
assert.equal(
|
||||
classifyProviderError(400, body, "antigravity"),
|
||||
PROVIDER_ERROR_TYPES.CONTEXT_OVERFLOW
|
||||
);
|
||||
});
|
||||
|
||||
test("#8136: a generic 400 bad-request body (no model-unavailable phrasing) is not reclassified as MODEL_NOT_FOUND", () => {
|
||||
const body = { error: { message: "Invalid request: missing required field 'messages'." } };
|
||||
assert.equal(classifyProviderError(400, body, "antigravity"), null);
|
||||
});
|
||||
Reference in New Issue
Block a user