From a05a7bb2f4b7f51f5000d73c068147c203eaac7e Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Thu, 23 Jul 2026 19:26:10 -0700 Subject: [PATCH] fix(status-bar): guard undefined provider window in usedPercent reduce (crashes d2c1da69, bb74236c) (#10271) Co-authored-by: Orca --- .../status-bar/UsageRosterPanel.tsx | 8 +++-- .../provider-segment-monthly-window.test.tsx | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/components/status-bar/UsageRosterPanel.tsx b/src/renderer/src/components/status-bar/UsageRosterPanel.tsx index c81e412dc..1e6752322 100644 --- a/src/renderer/src/components/status-bar/UsageRosterPanel.tsx +++ b/src/renderer/src/components/status-bar/UsageRosterPanel.tsx @@ -20,9 +20,13 @@ import type { StatusBarUsageMode } from '../../../../shared/status-bar-usage-mod type ProviderId = ProviderRateLimits['provider'] export type UsageSection = { label: string; window: RateLimitWindow } -// Windows/buckets that actually carry data — the null ones are absent limits. +// Windows/buckets that actually carry data — absent limits arrive as null, but a +// partial/rehydrated provider can also carry an undefined window; both must be +// dropped so downstream consumers never dereference `window.usedPercent`. function usedSections(p: ProviderRateLimits): UsageSection[] { - return getWindowSections(p).filter((s): s is UsageSection => s.window !== null) + return getWindowSections(p).filter( + (s): s is UsageSection => s.window !== null && s.window !== undefined + ) } function providerMaxUsed(sections: UsageSection[]): number { diff --git a/src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx b/src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx index ef4ec96e0..6e69a482d 100644 --- a/src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx +++ b/src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx @@ -168,3 +168,33 @@ describe('ProviderSegment monthly window', () => { expect(markup).not.toContain('40% used') }) }) + +describe('undefined provider window safety (crash d2c1da69 / bb74236c)', () => { + // A partial/rehydrated provider can carry an undefined (not null) window even + // though the type declares `session`/`weekly` as `RateLimitWindow | null`. The + // old `s.window !== null` filter let the undefined-window section through, so + // getTightestUsageSection's reduce read `.usedPercent` of undefined and crashed + // the status-bar overlay (TypeError in ProviderSegment). + const partialProvider = { + provider: 'codex', + weekly: windowOf(42, 10080), + updatedAt: Date.now(), + error: null, + status: 'ok' + } as unknown as ProviderRateLimits // `session` omitted -> undefined at runtime + + it('getTightestUsageSection ignores an undefined window instead of crashing', async () => { + const { getTightestUsageSection } = await import('./UsageRosterPanel') + expect(() => getTightestUsageSection(partialProvider)).not.toThrow() + expect(getTightestUsageSection(partialProvider)?.window.usedPercent).toBe(42) + }) + + it('ProviderSegment renders without crashing when a provider window is undefined', async () => { + const { ProviderSegment } = await import('./StatusBar') + expect(() => + renderToStaticMarkup( + + ) + ).not.toThrow() + }) +})