Switchbordswitchbord
v0.18.128

v0.18.128 — Inbox localStorage quota crash fix

Stops /inbox from crashing with QuotaExceededError on wedged browsers: the inbox persist write is now guarded with a slim-blob retry, and the unbounded persisted maps are capped.

Fixed


  • Inbox crash: QuotaExceededError from the switchbord-inbox persist blob. v0.18.116 moved composer drafts to IndexedDB, but two residual paths still crashed long-lived operator browsers on the current release. First, browsers already at the ~5 MB localStorage cap stay wedged: every setItem throws — even a smaller replacement, because the browser needs headroom during the write — so the v0.18.116 blob-shrink never landed for exactly the browsers that needed it. Second, the zustand persist setItem had no guard, so the throw unwound React's commit phase (observed in production via clearDraft) and took down the whole /inbox UI. The persist storage adapter is now guarded: a quota failure triggers a one-shot retry with a slim filters-only blob (tiny enough to fit in a wedged browser, breaking the wedge), and any storage failure is swallowed rather than thrown into the render tree. getItem/removeItem are guarded too.
  • Bounded growth for the remaining persisted maps. draftSeeds (full AI-draft message bodies per conversation) and softDeletedMessageIds grew without eviction. Both are now FIFO-capped (500 / 1000 entries respectively) at the mutation site and defensively at partialize, so the blob can never approach the quota again regardless of write path.

Verification


  • pnpm --filter app exec vitest run lib/inbox-persist-storage.test.ts stores/inbox-store.test.ts — 28 tests including the wedged-browser regression (quota-throwing setItem through the real store's clearDraft path asserts no throw + slim-blob shrink) and the eviction caps.
  • pnpm --filter app test — full app suite.
  • pnpm --filter app exec tsc --noEmit, pnpm lint — clean.