firebase / firebase/firebase-js-sdk

Auth: unhandled InvalidStateError 'transaction on IDBDatabase: connection is closing' from background persistence poller (Flutter Web, split from #2710)

Open
#10,149 0 comments 0 reactions 0 assignees View on GitHub
api: auth needs-attention stack:FlutterWeb
Dominant language
TypeScript
Stars
5.1k
Forks
1k
Avg merge
2d 21h
Merged PRs (30d)
37

Description

### [REQUIRED] Describe your environment

- Firebase JS SDK version: pinned by FlutterFire to **12.14.0** (current), but the same crash is reproducing across releases spanning JS SDK **12.2.1 → 12.14.0** in our production telemetry (i.e. it survives multiple SDK bumps, not tied to one version)
- Firebase Product: **Auth** (`indexedDBLocalPersistence`)
- Integration path: [FlutterFire](https://github.com/firebase/flutterfire) `firebase_auth: 6.5.2` / `firebase_auth_web: 6.2.2` / `firebase_core_web: 3.8.0` (Flutter Web)
- Browsers affected (from our error tracker, last ~3 months, production): Mobile Safari, Safari, Chrome (desktop), Chrome Mobile, Chrome Mobile iOS, Edge, and in-app browsers (Instagram webview) — **cross-browser**, not Safari-specific
- Platforms: patient- and clinician-facing Flutter Web apps

### Split out from #2710

Per [@hsubox76's request in #2710](https://github.com/firebase/firebase-js-sdk/issues/2710#issuecomment-4937836506): that thread is scoped to Firestore, while this and the last couple of reports there are all Auth, on Flutter Web. Filing this separately so it reaches the right owners.

### [REQUIRED] Describe the problem

#### Steps to reproduce

Not reliably reproducible on demand yet (see note below on the non-Flutter repro ask) — but consistently reproduces in production under normal usage: page load / tab foregrounding after the browser has been backgrounded or the IndexedDB connection has been torn down (tab close, reload, storage eviction, OS memory pressure evicting the tab). It is **not** tied to a specific user action — it fires from the SDK's own background persistence poller, so there's no application code path that triggers it and no way for consumers to catch it.

#### Relevant Code / stack trace

Captured stack (from our original report in #2710):

```
InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.
at isReadWrite (auth/src/platform_browser/persistence/indexed_db.ts:79)
at _poll → getObjectStore(db, false).getAll() (indexed_db.ts:363)
at _withRetries (indexed_db.ts:208)
```

Sequence: the background `_poll()` runs → `_withRetries` catches an underlying IndexedDB error and calls `db.close()` → the retry then calls `.transaction()` on the now-closing connection → `InvalidStateError` (`DOMException.code 11`), surfacing as an **unhandled promise rejection**. We also see a sibling `UnknownError: An internal error was encountered in the Indexed Database server` immediately before it in the same session.

`@flt-phy` reported the same file/line signature independently after bumping to JS SDK 12.5.0, also via Flutter Web + `firebase_auth`.

#### Production telemetry (Sentry), last ~3 months

Two of our top clusters (there are several smaller ones with the identical signature):

| Issue | Events | Users | Where it fires | App releases seen on |
|---|---|---|---|---|
| Cluster A | 323 | 306 | app root / `/patient` | `3.16.0+150`, `3.20.1+159`, `3.18.0+154` |
| Cluster B | 136 | 127 | app root / `/patient/login` | `3.20.0+156`, `3.20.1+159`, `3.18.0+154` |

Combined with the smaller clusters carrying the same message, we're at roughly **500+ events / 450+ distinct users** in this window, spread across unrelated app deploys — i.e. it's not caused by one of our releases, it's continuous background SDK behavior. Browser breakdown for Cluster A: Mobile Safari 98, Chrome 86, Chrome Mobile iOS 38, Edge 17, Safari 17, Instagram in-app 15 (remainder split across others) — confirming this isn't a Safari-only quirk.

None of this is user-visible (no data loss observed on our end, unlike some earlier reports in #2710) — but it's pure noise in our error tracker at meaningful volume, with no application-level way to suppress it since it doesn't originate from a call we make.

### On the non-Flutter repro ask

Understood, and agreed that's the most useful thing to nail down — it would rule out FlutterFire's JS interop/teardown handling as the culprit rather than the JS SDK's own persistence poller. We'll attempt a minimal vanilla-JS repro (`getAuth()` + `indexedDBLocalPersistence` + tab backgrounding/reload/storage-eviction) and report back here with either a working repro or a clear "doesn't reproduce outside Flutter" result.

### Possible direction (for consideration, not prescriptive)

Per [@schmidt-sebastian's earlier comment in #2710](https://github.com/firebase/firebase-js-sdk/issues/2710#issuecomment-680899309): user-initiated Auth operations already reject cleanly on IndexedDB failure so calling code can retry. This looks like the one code path that doesn't go through that handling — the background `_poll()`/`_withRetries` loop's own retry-after-`close()` race. If confirmed as SDK-internal (not FlutterFire), catching/discarding `InvalidStateError`/closing-connection failures specifically inside the poller (rather than the calling code, which is exactly what we don't have a code path to catch) seems like it would fix this at the source without changing user-facing retry semantics.

/cc @flt-phy

Contributor guide

Open the contributing guide

Research direction

Start in auth/src/platform_browser/persistence/indexed_db.ts, especially isReadWrite, _poll, and _withRetries, and trace the retry path after db.close(). Try to reproduce the connection-closing failure with the reported backgrounding or reload scenarios, including a minimal vanilla-JS setup. Done means the poller no longer surfaces this failure as an unhandled promise rejection without changing user-initiated Auth retry behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
firebase, typescript
Domain
authentication
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.