← Back to PRs

#17414: fix(sessions): refresh contextTokens when model override changes

by michaelbship open 2026-02-15 18:40 View on GitHub →
stale size: XS
## Summary - When `applyModelOverrideToSessionEntry()` switches the active model, `entry.contextTokens` retains the previous model's context window - Every downstream consumer — compaction threshold, memory flush, session persistence, `/status` display — sees the stale value - Fix: call `lookupContextTokens()` after the override is applied and write the result back to `entry.contextTokens` - Also handles the revert-to-default case by deleting `contextTokens` so it gets re-resolved from config ## Problem Switching models mid-session via `/model` (or alias, failover, quota exhaustion) leaves `entry.contextTokens` set to the previous model's value. For example, switching from Sonnet 4.5 (1M context) to Opus 4.6 (200K) leaves the session believing it has 1M tokens of headroom. Compaction never fires, and the session grows until the API rejects it with a context-length error. ## Root Cause `applyModelOverrideToSessionEntry()` in `src/sessions/model-overrides.ts` updates `entry.modelOverride` and `entry.providerOverride` but does not touch `entry.contextTokens`: ```ts if (selection.model !== entry.modelOverride) { entry.modelOverride = selection.model; updated = true; } // contextTokens is never refreshed here ``` The `??` fallback chain at most callsites reads `entry.contextTokens` first: ```ts entry?.contextTokens ?? lookupContextTokens(model) ?? DEFAULT_CONTEXT_TOKENS ``` Since `entry.contextTokens` is already set (from the previous model), the fallback to `lookupContextTokens()` never triggers. ## Fix After detecting that the model override was `updated`, call `lookupContextTokens(effectiveModel)` and write the fresh value back to `entry.contextTokens`. When the override is reverted (no effective model), delete `contextTokens` so it gets re-resolved from config. ```ts if (updated) { const effectiveModel = entry.modelOverride; if (effectiveModel) { const fresh = lookupContextTokens(effectiveModel); if (typeof fresh === "number" && fresh > 0) { entry.contextTokens = fresh; } } else { // Reverted to default — clear so it gets re-resolved from config. delete entry.contextTokens; } entry.updatedAt = Date.now(); } ``` Fixes #8240 ## Testing - Verified that `/status` displays the correct context window after switching models via `/model` alias - Verified that reverting to the default model clears the stale value - Existing tests pass ## AI Disclosure This PR was authored with AI assistance. Generated with [Claude Code](https://claude.com/claude-code) <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a critical bug where switching models mid-session via `/model` left `entry.contextTokens` set to the previous model's context window size. The fix introduces a `modelChanged` flag to track model/provider changes separately from auth profile changes, then refreshes `contextTokens` by calling `lookupContextTokens()` when the model changes. When reverting to default, it properly clears `contextTokens` so it gets re-resolved from config. - Addresses the efficiency concern from the previous review thread by only refreshing `contextTokens` when model/provider actually changes, not on profile-only updates - Prevents compaction failures and context-length API errors that occur when session believes it has more headroom than it actually does - Handles both model switch and revert-to-default cases correctly <h3>Confidence Score: 5/5</h3> - This PR is safe to merge - it fixes a critical context window bug with a well-targeted solution - The fix is surgical and correct: introduces a separate `modelChanged` flag to distinguish model changes from profile-only changes, refreshes `contextTokens` only when needed, and properly handles both model switch and revert cases. The logic is straightforward with appropriate guard conditions (type and value checks before setting `contextTokens`). This directly addresses the root cause described in the PR without touching unrelated code paths. - No files require special attention <sub>Last reviewed commit: 90c66f3</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs