Classify WebKit 'without an in-progress transaction' IndexedDB errors as transient - #832
Open
sosek108 wants to merge 1 commit into
Open
Conversation
This was referenced Aug 31, 2026
sosek108
marked this pull request as ready for review
September 1, 2026 14:28
melvin-bot
Bot
requested review from
MonilBhavsar
and removed request for
a team
September 1, 2026 14:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Details
WebKit's IndexedDB server can tear down transactions under a live connection (page reload, or foregrounding a tab after process suspension). When that happens, every in-flight operation fails with an
UnknownErrorDOMException from the same family:Attempt to get a record from database without an in-progress transactionAttempt to get records from database without an in-progress transactionAttempt to generate key in database without an in-progress transactionThese are emitted by WebKit's
SQLiteIDBBackingStoreand only ever occur on WebKit browsers (iOS Safari, Chrome/Edge/Google iOS shells, macOS Safari) — Sentry tag distribution on the linked issue is 100% WebKit.classifyIDBErrorcurrently classifies them asUNKNOWN, so the connection layer propagates them without retrying. The visible damage is at app boot: the initialgetAllfails and Onyx boots with default key states only ("Failed to load data from storage during init"), dropping the whole local cache for that session even though the data is intact on disk.Production logs show that sibling errors from the very same failure episodes (
AbortError-flavored aborts) are already classifiedTRANSIENTand recover on the same-instant reopen-and-retry. This PR extends theTRANSIENTbucket to thewithout an in-progress transactionfamily (matched on the shared message suffix), so the connection layer drops the stale cached connection and retries once with a fresh one instead of giving up.Related Issues
Expensify/App#100046
Linked E/App PR
Expensify/App#99900
Automated Tests
Added two tests to
createStoreTest.tsmirroring the existing transient-retry coverage:should retry once and succeed on a WebKit "without an in-progress transaction" UnknownError— read path: first transaction fails with the WebKitUnknownError, the connection layer logsIDB transient error, reopens, and the read succeeds.should retry once and succeed on a WebKit "generate key" UnknownError during a write— write path: same recovery for areadwritetransaction, and the written value is readable afterwards.Manual Tests
[Onyx] IDB transient error — dropping cached connection and retrying once(instead ofIDB error not recoverable at the connection layer, propagating), the action completes, and the data survives a page reload.Author Checklist
### Related Issuessection above### Linked E/App PRsection above, and verified this change against it (E/App CI passed and manual testing completed)TestssectiontoggleReportand notonIconClick)myBool && <MyComponent />.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)Avataris modified, I verified thatAvataris working as expected in all cases)mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari