diff --git a/src/sessions/model-overrides.test.ts b/src/sessions/model-overrides.test.ts index 7545cd49548..9226de3ceaa 100644 --- a/src/sessions/model-overrides.test.ts +++ b/src/sessions/model-overrides.test.ts @@ -92,6 +92,34 @@ describe("applyModelOverrideToSessionEntry", () => { expect(entry.updatedAt).toBe(before); }); + it("rejects empty provider or model IDs without mutating the entry", () => { + const before = Date.now() - 5_000; + const entry: SessionEntry = { + sessionId: "sess-empty", + updatedAt: before, + providerOverride: "anthropic", + modelOverride: "claude-sonnet-4-6", + }; + + const emptyProvider = applyModelOverrideToSessionEntry({ + entry, + selection: { provider: "", model: "gpt-5.2" }, + }); + expect(emptyProvider.updated).toBe(false); + expect(entry.providerOverride).toBe("anthropic"); + expect(entry.modelOverride).toBe("claude-sonnet-4-6"); + expect(entry.updatedAt).toBe(before); + + const emptyModel = applyModelOverrideToSessionEntry({ + entry, + selection: { provider: "openai", model: " " }, + }); + expect(emptyModel.updated).toBe(false); + expect(entry.providerOverride).toBe("anthropic"); + expect(entry.modelOverride).toBe("claude-sonnet-4-6"); + expect(entry.updatedAt).toBe(before); + }); + it("clears stale contextTokens when switching back to the default model", () => { const before = Date.now() - 5_000; const entry: SessionEntry = { diff --git a/src/sessions/model-overrides.ts b/src/sessions/model-overrides.ts index dbbc95e23b7..a4190aef959 100644 --- a/src/sessions/model-overrides.ts +++ b/src/sessions/model-overrides.ts @@ -17,6 +17,12 @@ export function applyModelOverrideToSessionEntry(params: { let updated = false; let selectionUpdated = false; + // Guard against empty/whitespace-only provider or model IDs that can result + // from truncated picker payloads or malformed directive parsing (#46700). + if (!selection.isDefault && (!selection.provider.trim() || !selection.model.trim())) { + return { updated: false }; + } + if (selection.isDefault) { if (entry.providerOverride) { delete entry.providerOverride;