Skip to content

fix(storage): fall back to memory when IndexedDB is unavailable - #759

Open
erhnysr wants to merge 1 commit into
tempoxyz:mainfrom
erhnysr:fix/idb-memory-fallback
Open

fix(storage): fall back to memory when IndexedDB is unavailable#759
erhnysr wants to merge 1 commit into
tempoxyz:mainfrom
erhnysr:fix/idb-memory-fallback

Conversation

@erhnysr

@erhnysr erhnysr commented Aug 12, 2026

Copy link
Copy Markdown

Problem

Storage.idb() guards on window before selecting IndexedDB-backed storage, but never checks for indexedDB itself. In a runtime that exposes a partial window without IndexedDB — React Native and Expo, some SSR setups — idb() is still chosen as the default, and the first read or write throws ReferenceError: indexedDB is not defined.

The underlying cause is that idb-keyval treats an undefined store as "use the default store", which opens IndexedDB unconditionally. So the existing typeof indexedDB !== 'undefined' check inside the function never prevents anything — the delegation happens anyway.

AGENTS.md:106 already calls this out as a rule:

React Native may expose window without IndexedDB — storage defaults that mean "browser" should guard on indexedDB, not window, or Expo/React Native can try to use IndexedDB-backed storage and throw at startup.

This change brings the code into line with that rule rather than introducing a new policy.

Fix

Storage.idb() now falls back to the existing in-memory adapter when IndexedDB isn't available, instead of delegating to idb-keyval's default store.

Putting the fallback inside idb() fixes it at the root: all three default-storage call sites funnel through this function, so a partial-window runtime gets a working adapter — session persistence with structured-clone semantics via memory()'s markStructuredClone — rather than a startup crash. No changes to Provider.ts.

Tests

src/core/Storage.test.ts asserts typeof indexedDB === 'undefined' as a precondition, then exercises set / get / remove through idb(). Verified failing-first: before the change the first setItem throws.

Changeset

patch. No new API and no new capability for setups that already work — a crash becomes functioning degraded behaviour. This matches the bump used for the directly comparable guard fixes, #706 (crypto.randomUUID guard) and #734 (partial-window announcement guard).

Note on the trade-off

An app that previously crashed loudly at startup will now silently persist to memory instead, so persistence across reloads won't happen in that runtime. That's the same way the window-guarded defaults already degrade for SSR, and it's what the existing indexedDB check was evidently meant to do.

If you'd rather fail loudly — a clear Error('Storage.idb requires IndexedDB') instead of degrading — that's a reasonable alternative, but it would leave the React Native default path crashing unless the three call sites also switch to memory(). Happy to take it that direction if you prefer.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

@erhnysr is attempting to deploy a commit to the Tempo Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant