From c5068d37d22cfdd09f7fe28b5d4aca8aaa21f554 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 28 Mar 2026 00:42:52 +0900 Subject: [PATCH] fix(#2885): add model_not_supported to RETRYABLE error patterns model_not_supported errors from providers (e.g. OpenAI returning {"error": {"code": "model_not_supported"}}) were not recognized as retryable. Subagents would silently fail with no response, hanging the parent session. Fix: - Add "model_not_supported", "model not supported", "model is not supported" to RETRYABLE_MESSAGE_PATTERNS in model-error-classifier.ts - Add regex patterns to RETRYABLE_ERROR_PATTERNS in runtime-fallback/constants.ts to match "model ... is ... not ... supported" with flexible spacing - Add regression test covering all three variations Now model_not_supported errors trigger the normal fallback chain instead of silent failure. --- src/hooks/runtime-fallback/constants.ts | 2 ++ .../runtime-fallback/error-classifier.test.ts | 17 +++++++++++++++++ src/shared/model-error-classifier.ts | 3 +++ 3 files changed, 22 insertions(+) diff --git a/src/hooks/runtime-fallback/constants.ts b/src/hooks/runtime-fallback/constants.ts index 3bd4409a4..eaf4e78c5 100644 --- a/src/hooks/runtime-fallback/constants.ts +++ b/src/hooks/runtime-fallback/constants.ts @@ -31,6 +31,8 @@ export const RETRYABLE_ERROR_PATTERNS = [ /cool(?:ing)?\s+down/i, /exhausted\s+your\s+capacity/i, /usage\s+limit\s+has\s+been\s+reached/i, + /model.{0,20}?not.{0,10}?supported/i, + /model_not_supported/i, /service.?unavailable/i, /overloaded/i, /temporarily.?unavailable/i, diff --git a/src/hooks/runtime-fallback/error-classifier.test.ts b/src/hooks/runtime-fallback/error-classifier.test.ts index 01bfe3d3e..f738ebce9 100644 --- a/src/hooks/runtime-fallback/error-classifier.test.ts +++ b/src/hooks/runtime-fallback/error-classifier.test.ts @@ -276,4 +276,21 @@ describe("quota error detection (fixes #2747)", () => { expect(errorType).toBe("quota_exceeded") expect(retryable).toBe(true) }) + + test("detects model_not_supported errors as retryable for fallback chain", () => { + //#given + const error1 = { message: "model_not_supported" } + const error2 = { message: "The model 'gpt-4-foo' is not supported by this API" } + const error3 = { message: "model not supported on free tier" } + + //#when + const retryable1 = isRetryableError(error1, [400, 404]) + const retryable2 = isRetryableError(error2, [400, 404]) + const retryable3 = isRetryableError(error3, [400, 404]) + + //#then + expect(retryable1).toBe(true) + expect(retryable2).toBe(true) + expect(retryable3).toBe(true) + }) }) diff --git a/src/shared/model-error-classifier.ts b/src/shared/model-error-classifier.ts index 3c3af4982..5868aefec 100644 --- a/src/shared/model-error-classifier.ts +++ b/src/shared/model-error-classifier.ts @@ -51,6 +51,9 @@ const RETRYABLE_MESSAGE_PATTERNS = [ "bad gateway", "unknown provider", "provider not found", + "model_not_supported", + "model not supported", + "model is not supported", "connection error", "network error", "timeout",