From 0f27cff247619163dca2b6cc8b17cd3e6de9c390 Mon Sep 17 00:00:00 2001 From: Roshan Singh Date: Thu, 15 Jan 2026 11:58:15 +0000 Subject: [PATCH 1/2] Fix model fallback crash on undefined provider/model (#946) --- src/agents/model-fallback.test.ts | 28 ++++++++++++++++++++++++++++ src/agents/model-fallback.ts | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/agents/model-fallback.test.ts b/src/agents/model-fallback.test.ts index 160deb7e1..381da47ff 100644 --- a/src/agents/model-fallback.test.ts +++ b/src/agents/model-fallback.test.ts @@ -213,6 +213,34 @@ describe("runWithModelFallback", () => { expect(calls).toEqual([{ provider: "anthropic", model: "claude-opus-4-5" }]); }); + it("defaults provider/model when missing (regression #946)", async () => { + const cfg = makeCfg({ + agents: { + defaults: { + model: { + primary: "openai/gpt-4.1-mini", + fallbacks: [], + }, + }, + }, + }); + + const calls: Array<{ provider: string; model: string }> = []; + + const result = await runWithModelFallback({ + cfg, + provider: undefined as unknown as string, + model: undefined as unknown as string, + run: async (provider, model) => { + calls.push({ provider, model }); + return "ok"; + }, + }); + + expect(result.result).toBe("ok"); + expect(calls).toEqual([{ provider: "openai", model: "gpt-4.1-mini" }]); + }); + it("falls back on missing API key errors", async () => { const cfg = makeCfg(); const run = vi diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index f3d7e7d52..f407a4cbf 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -119,8 +119,8 @@ function resolveFallbackCandidates(params: { /** Optional explicit fallbacks list; when provided (even empty), replaces agents.defaults.model.fallbacks. */ fallbacksOverride?: string[]; }): ModelCandidate[] { - const provider = params.provider.trim() || DEFAULT_PROVIDER; - const model = params.model.trim() || DEFAULT_MODEL; + const provider = String(params.provider ?? "").trim() || DEFAULT_PROVIDER; + const model = String(params.model ?? "").trim() || DEFAULT_MODEL; const primary = params.cfg ? resolveConfiguredModelRef({ cfg: params.cfg, From c043e9767f4094c2069352d4202bf4ec61baccfe Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 15 Jan 2026 16:58:41 +0000 Subject: [PATCH 2/2] fix: default model fallback when provider/model missing (#954) (thanks @roshanasingh4) --- CHANGELOG.md | 2 +- src/agents/model-fallback.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e975296d6..0452e772b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 2026.1.15 (unreleased) -- TBD +- Fix: guard model fallback against undefined provider/model values. (#954) — thanks @roshanasingh4. ## 2026.1.14-1 diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index f407a4cbf..469f45a2c 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -119,8 +119,6 @@ function resolveFallbackCandidates(params: { /** Optional explicit fallbacks list; when provided (even empty), replaces agents.defaults.model.fallbacks. */ fallbacksOverride?: string[]; }): ModelCandidate[] { - const provider = String(params.provider ?? "").trim() || DEFAULT_PROVIDER; - const model = String(params.model ?? "").trim() || DEFAULT_MODEL; const primary = params.cfg ? resolveConfiguredModelRef({ cfg: params.cfg, @@ -128,11 +126,15 @@ function resolveFallbackCandidates(params: { defaultModel: DEFAULT_MODEL, }) : null; + const defaultProvider = primary?.provider ?? DEFAULT_PROVIDER; + const defaultModel = primary?.model ?? DEFAULT_MODEL; + const provider = String(params.provider ?? "").trim() || defaultProvider; + const model = String(params.model ?? "").trim() || defaultModel; const aliasIndex = buildModelAliasIndex({ cfg: params.cfg ?? {}, - defaultProvider: DEFAULT_PROVIDER, + defaultProvider, }); - const allowlist = buildAllowedModelKeys(params.cfg, DEFAULT_PROVIDER); + const allowlist = buildAllowedModelKeys(params.cfg, defaultProvider); const seen = new Set(); const candidates: ModelCandidate[] = []; @@ -160,7 +162,7 @@ function resolveFallbackCandidates(params: { for (const raw of modelFallbacks) { const resolved = resolveModelRefFromString({ raw: String(raw ?? ""), - defaultProvider: DEFAULT_PROVIDER, + defaultProvider, aliasIndex, }); if (!resolved) continue;