You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Onyx] Investigate QuotaExceededError: Encountered full disk while opening backing store for indexedDB.open. storage error #87866
Let's investigate the following Onyx storage error: QuotaExceededError: Encountered full disk while opening backing store for indexedDB.open., which accounts for 234,697 (7.0%) of the 3,364,645 analysed errors during a time span of 1 month. Full details about the investigation and methodology are in #87844.
Platforms
Top Methods
Desktop Chrome (205K), Desktop Edge (21K), Desktop Opera (9K)
setWithRetry (232K)
Retries Exhausted
Evictions
No Eviction
Quota Checks
>= 95% Full
Mean % Full
Quota Check Failed
6
234,222
471
16,327
0
0.0%
475
0 at >= 95% and mean 0.0% full despite "full disk" in the error — this reflects IndexedDB's per-origin quota being exhausted, not the actual disk being full. The browser allocates a fraction of total storage to each origin, so "full disk" is a misnomer from Chromium
Very few requests exhausted retries (6), suggesting eviction generally resolves the issue
Action Items
Investigate with Sentry, VictoriaLogs and Fullstory to understand user scenarios — are these users with genuinely large Onyx stores, or is something else consuming the origin's quota?
471 requests hit the "no evictable keys" dead end — review whether more Onyx keys could be added to the evictableKeys list for these cases
Investigate with Sentry, VictoriaLogs and Fullstory to understand user scenarios — are these users with genuinely large Onyx stores, or is something else consuming the origin's quota?
I've checked in VictoriaLogs and 100% of Out of storage. But found no acceptable keys to remove errors are not connected to any email. Query "Out of storage. But found no acceptable keys to remove" and email returned with zero hits over last 30 days.
From what I saw in the internet, it can be another bug in chrome - sometimes restart of the browser helps. Of course there can be also a real scenario where there is no more space on the disk, but I think it should be quite rare.
The error message QuotaExceededError: Encountered full disk while opening backing store for indexedDB.open. is misleading — it does not indicate actual disk or quota exhaustion in the majority of cases. Our telemetry confirms this: 0% mean storage usage and 0 users at ≥95% full across 234,697 occurrences.
How Chromium generates this error
Chromium uses LevelDB as the backing store for IndexedDB. When indexedDB.open() is called, Chrome invokes IndexedDBBackingStore::Open() → leveldb_factory->OpenLevelDB(). If LevelDB returns an IOError, Chrome checks it with leveldb_env::IndicatesDiskFull(status) — a heuristic on the LevelDB status code, not an actual disk space check. When this heuristic fires, Chrome sets disk_full = true and surfaces the QuotaExceededError to JavaScript (source: indexed_db_factory.cc, source: indexed_db_backing_store.cc).
This means LevelDB-level issues (stale lock files, corrupted metadata, QuotaManager inconsistency) are misreported as quota errors.
Known Chromium bugs contributing to false positives
After a failed write near quota, database becomes permanently inaccessible with this error — even after freeing space. Only browser restart recovers it
Chrome 99+ bug: QuotaManager database (separate from IDB) gets corrupted, making Chrome think the origin is over quota. Restart rebuilds it
Browser restart as the universal fix
Multiple sources confirm that restarting Chrome resolves this error because it:
Releases all LevelDB lock files held by the browser process
Rebuilds the QuotaManager database from scratch
Forces all IDB connections to close and reopen cleanly
This is documented by PixieBrix and confirmed in Chromium bug discussions.
Can Onyx's heal mechanism help?
Unlikely for most cases. Unlike the backing store corruption error (UnknownError: Internal error opening backing store) where the problem is a stale cached dbp in our code, this error originates from Chrome's IDB infrastructure actively refusing indexedDB.open(). A fresh JS-level indexedDB.open() call hits the same Chrome-level state (corrupted QuotaManager, held LevelDB locks).
However, the current eviction path resolves this 99.997% of the time (only 6 out of 234,697 exhausted retries). Two hypotheses for why:
Some are genuine (mild) quota hits where eviction legitimately frees enough space
The async delay during eviction (multiple storage operations) gives Chrome enough time to internally release locks and recover — it's the delay, not the data deletion, that helps
Impact Assessment
Metric
Value
Monthly occurrences
234,697 (7.0% of all storage errors)
Platforms
Chromium-only: Chrome (205K), Edge (21K), Opera (9K)
Recovery rate
99.997% (only 6 exhausted all retries)
Unnecessary evictions
Up to 234,222/month (if most are false positives)
"No evictable keys" dead ends
471
Quota check failures
475 (navigator.storage.estimate() itself threw)
Recommendations
Instrument to distinguish real vs false-positive quota errors. Add logging that captures:
The result of navigator.storage.estimate() at the time of error (bytes used vs quota)
Whether the error is transient (resolves on next retry) or persistent (requires eviction/restart)
This data will tell us what proportion are Chrome bugs vs genuine quota exhaustion
Consider a retry-with-delay before eviction. If the async delay during eviction is what actually helps (hypothesis Fix spaces #2), a simple delayed retry before triggering eviction could avoid unnecessary data deletion. This could be implemented in OnyxUtils.retryOperation as a short backoff (e.g. 100–500ms) specifically for this error pattern before falling back to the eviction path.
Expand evictableKeys for the 471 dead-end cases. These users hit the error, eviction was triggered, but no keys were available to remove. Review which Onyx keys could be added to the evictable list.
Do not add to the heal mechanism in createStore.ts. The heal (drop dbp, immediate reopen) would likely fail for the same reason, waste a budget attempt, and the error would propagate to eviction anyway. The cacheOpenPromise rejection cleanup in PR Update version to 1.0.1-177 #780 already prevents stale rejected promises from blocking subsequent operations, which is sufficient at the createStore level.
The error QuotaExceededError: Encountered full disk while opening backing store for indexedDB.open. accounts for 234,697 (7.0%) of all Onyx storage errors per month. It is 100% Chromium-based (Chrome, Edge, Opera) and occurs during indexedDB.open(), not during write transactions.
Sentry Analysis (90-day window)
Two Sentry issues capture this error as an unhandled rejection (after all Onyx retries + eviction failed):
Several users hit this error 3–5 times over weeks (e.g. user 10634764 on May 20 and May 27), consistent with a persistent corrupted browser/profile state that recurs until something forces a reset.
Fullstory Session Analysis
Built a Fullstory segment matching sessions with this console error (last 90 days, 20+ sessions returned). Examined 4 sessions in detail:
Finding 1: The "full disk" error is always preceded by another IDB error
In every session examined, the QuotaExceededError was a secondary/cascade error, never the root cause:
Session A (user on /home): Error appears at 10.6s with no prior user action — immediately hits "Out of storage. But found no acceptable keys to remove", suggesting the IDB was already in a broken state from a previous page load or session.
Session B (user browsing reports + settings): Starts with AbortError: The transaction was aborted → then UnknownError: Internal error opening backing store (error Some initial fixes and code style updates #1, backing store corruption) — the full-disk error never appears here, but the same LevelDB corruption is the root cause.
Session C (user submitting expenses): UnknownError: Connection is closing → IDB InvalidStateError, retrying with fresh connection → then QuotaExceededError: Encountered full disk. Clear cascade: connection issue corrupts LevelDB state, which then reports false "full disk".
Session D (user browsing expense reports): DataError: Failed to write blobs (IOError) → null error → then QuotaExceededError: Encountered full disk. Another cascade: blob write failure leads to corrupted backing store state.
Finding 2: Infinite background error loop
Once the error starts, it never self-heals within the session. The pattern in every affected session:
Error fires → eviction triggered → no evictable keys found → retryOperation resolves silently (write skipped)
~30 seconds later: a periodic Onyx operation (likely API response handling) triggers another write
Same error → same failed eviction → same silent skip
Repeats every 30s for the entire session — Session A logged 80+ repetitions spanning 40 minutes, Session D logged 20+ repetitions spanning 18 minutes
This means a single occurrence of the underlying Chrome bug generates dozens to hundreds of error log entries per session. The 234K monthly error count likely represents far fewer actual affected sessions than it appears.
Finding 3: Users don't know their data is being lost
In Sessions C and D, users continued actively working — submitting expenses, editing fields, navigating between reports — for 10+ minutes after the errors started. Every Onyx write during this time silently failed. The app remained visually functional because it reads from the in-memory cache, but nothing was persisted to IDB. Any data entered during this window is lost on page refresh.
Finding 4: Co-occurrence with backing store corruption (APP-17G breadcrumbs)
In the latest APP-17G Sentry event, the breadcrumb trail shows UnknownError: Internal error opening backing store for indexedDB.open. occurring 200ms before the QuotaExceededError. Both errors in the same session, same user — strongly confirming they share the same root cause: LevelDB backing store in a corrupted state.
Root Cause: Chromium Bug, Not Real Quota Exhaustion
Evidence summary
Telemetry: 0% mean storage usage and 0 users at ≥95% full across 234K occurrences
Fullstory: Error is always preceded by another IDB failure (connection closing, backing store corruption, blob write failure) — the "full disk" is a false positive triggered by LevelDB corruption
Repeat users over weeks: Persistent profile-level issue, not transient storage pressure
Chromium source code: The disk_full flag comes from leveldb_env::IndicatesDiskFull(status) — a heuristic on LevelDB's status code, not an actual disk space check
Known Chromium bugs:
chromium#340398745 — "Investigate why opening IndexedDB LevelDB backing store fails on Lock so often"
chromium#279106 — database becomes permanently inaccessible with this error even after freeing space; only browser restart recovers
QuotaManager corruption — Chrome 99+ bug where QuotaManager database gets corrupted, making Chrome think the origin is over quota
Browser restart is the universal fix — confirmed by PixieBrix and Chromium bug discussions. Restart releases LevelDB locks, rebuilds QuotaManager, forces fresh IDB connections.
Why the current eviction path works 99.997% of the time
Only 6 out of 234,697 occurrences exhausted all retries. Two hypotheses:
Some are genuine (mild) quota hits where eviction legitimately frees enough space
The async delay during eviction (find key → delete key → retry) gives Chrome enough time to internally release locks — it's the delay, not the data deletion, that helps
Not directly. Unlike backing store corruption where the problem is a stale cached dbp, this error originates from Chrome's IDB infrastructure actively refusing indexedDB.open(). A fresh JS-level indexedDB.open() call hits the same Chrome-level state. The cacheOpenPromise rejection cleanup in #780 already prevents stale rejected promises from blocking subsequent operations, which is sufficient at the createStore level.
However, the Fullstory data shows that the "full disk" error frequently co-occurs with or follows the backing store corruption error (#1) and connection closing error (#3) — both of which #780 does heal. Fixing those upstream errors may reduce the cascade into false "full disk" errors.
Key Takeaways
The "full disk" error is a symptom, not the disease. The real root cause is LevelDB backing store corruption in Chromium. The QuotaExceededError is a misclassified cascade error.
The 234K monthly count is inflated. A single affected session generates 30-80+ error entries due to the infinite retry loop (~30s interval). The actual number of affected user-sessions is orders of magnitude smaller.
Silent data loss is the real impact. Users continue working while every write silently fails. The app looks functional (reads from memory cache) but nothing persists to IDB.
Existing infrastructure can help filter false positives. Onyx already calls navigator.storage.estimate() via getDatabaseSize() on every eviction — but only logs the result, never uses it for decision-making. The data consistently shows 0% usage for these errors. Using this signal to skip eviction and retry with a delay instead could avoid unnecessary data deletion.
The infinite retry loop needs a circuit breaker. Once "no acceptable keys to remove" fires for a given error, subsequent retries for the same root cause will also fail. A mechanism to stop retrying the same failing operation (or at least back off exponentially) would reduce log noise and wasted CPU.
Activity
sosek108 commentedon May 26, 2026
I've checked in VictoriaLogs and 100% of
Out of storage. But found no acceptable keys to removeerrors are not connected to any email. Query"Out of storage. But found no acceptable keys to remove" and emailreturned with zero hits over last 30 days.leshniak commentedon May 26, 2026
I'll take it.
From what I saw in the internet, it can be another bug in chrome - sometimes restart of the browser helps. Of course there can be also a real scenario where there is no more space on the disk, but I think it should be quite rare.
I'll go deeper.
leshniak commentedon May 27, 2026
Investigation Report
Root Cause Analysis
The error message
QuotaExceededError: Encountered full disk while opening backing store for indexedDB.open.is misleading — it does not indicate actual disk or quota exhaustion in the majority of cases. Our telemetry confirms this: 0% mean storage usage and 0 users at ≥95% full across 234,697 occurrences.How Chromium generates this error
Chromium uses LevelDB as the backing store for IndexedDB. When
indexedDB.open()is called, Chrome invokesIndexedDBBackingStore::Open()→leveldb_factory->OpenLevelDB(). If LevelDB returns an IOError, Chrome checks it withleveldb_env::IndicatesDiskFull(status)— a heuristic on the LevelDB status code, not an actual disk space check. When this heuristic fires, Chrome setsdisk_full = trueand surfaces theQuotaExceededErrorto JavaScript (source: indexed_db_factory.cc, source: indexed_db_backing_store.cc).This means LevelDB-level issues (stale lock files, corrupted metadata, QuotaManager inconsistency) are misreported as quota errors.
Known Chromium bugs contributing to false positives
Browser restart as the universal fix
Multiple sources confirm that restarting Chrome resolves this error because it:
This is documented by PixieBrix and confirmed in Chromium bug discussions.
Can Onyx's heal mechanism help?
Unlikely for most cases. Unlike the backing store corruption error (
UnknownError: Internal error opening backing store) where the problem is a stale cacheddbpin our code, this error originates from Chrome's IDB infrastructure actively refusingindexedDB.open(). A fresh JS-levelindexedDB.open()call hits the same Chrome-level state (corrupted QuotaManager, held LevelDB locks).However, the current eviction path resolves this 99.997% of the time (only 6 out of 234,697 exhausted retries). Two hypotheses for why:
Impact Assessment
navigator.storage.estimate()itself threw)Recommendations
Instrument to distinguish real vs false-positive quota errors. Add logging that captures:
navigator.storage.estimate()at the time of error (bytes used vs quota)Consider a retry-with-delay before eviction. If the async delay during eviction is what actually helps (hypothesis Fix spaces #2), a simple delayed retry before triggering eviction could avoid unnecessary data deletion. This could be implemented in
OnyxUtils.retryOperationas a short backoff (e.g. 100–500ms) specifically for this error pattern before falling back to the eviction path.Expand
evictableKeysfor the 471 dead-end cases. These users hit the error, eviction was triggered, but no keys were available to remove. Review which Onyx keys could be added to the evictable list.Do not add to the heal mechanism in
createStore.ts. The heal (dropdbp, immediate reopen) would likely fail for the same reason, waste a budget attempt, and the error would propagate to eviction anyway. ThecacheOpenPromiserejection cleanup in PR Update version to 1.0.1-177 #780 already prevents stale rejected promises from blocking subsequent operations, which is sufficient at thecreateStorelevel.sosek108 commentedon May 29, 2026
Hi, I'll be continuing investigation here
leshniak commentedon May 29, 2026
Investigation Update
Error Identification
The error
QuotaExceededError: Encountered full disk while opening backing store for indexedDB.open.accounts for 234,697 (7.0%) of all Onyx storage errors per month. It is 100% Chromium-based (Chrome, Edge, Opera) and occurs duringindexedDB.open(), not during write transactions.Sentry Analysis (90-day window)
Two Sentry issues capture this error as an unhandled rejection (after all Onyx retries + eviction failed):
Platform breakdown (90d):
~95% Windows. 100% Chromium-based.
Several users hit this error 3–5 times over weeks (e.g. user
10634764on May 20 and May 27), consistent with a persistent corrupted browser/profile state that recurs until something forces a reset.Fullstory Session Analysis
Built a Fullstory segment matching sessions with this console error (last 90 days, 20+ sessions returned). Examined 4 sessions in detail:
Finding 1: The "full disk" error is always preceded by another IDB error
In every session examined, the
QuotaExceededErrorwas a secondary/cascade error, never the root cause:/home): Error appears at 10.6s with no prior user action — immediately hits"Out of storage. But found no acceptable keys to remove", suggesting the IDB was already in a broken state from a previous page load or session.AbortError: The transaction was aborted→ thenUnknownError: Internal error opening backing store(error Some initial fixes and code style updates #1, backing store corruption) — the full-disk error never appears here, but the same LevelDB corruption is the root cause.UnknownError: Connection is closing→IDB InvalidStateError, retrying with fresh connection→ thenQuotaExceededError: Encountered full disk. Clear cascade: connection issue corrupts LevelDB state, which then reports false "full disk".DataError: Failed to write blobs (IOError)→nullerror → thenQuotaExceededError: Encountered full disk. Another cascade: blob write failure leads to corrupted backing store state.Finding 2: Infinite background error loop
Once the error starts, it never self-heals within the session. The pattern in every affected session:
retryOperationresolves silently (write skipped)This means a single occurrence of the underlying Chrome bug generates dozens to hundreds of error log entries per session. The 234K monthly error count likely represents far fewer actual affected sessions than it appears.
Finding 3: Users don't know their data is being lost
In Sessions C and D, users continued actively working — submitting expenses, editing fields, navigating between reports — for 10+ minutes after the errors started. Every Onyx write during this time silently failed. The app remained visually functional because it reads from the in-memory cache, but nothing was persisted to IDB. Any data entered during this window is lost on page refresh.
Finding 4: Co-occurrence with backing store corruption (APP-17G breadcrumbs)
In the latest APP-17G Sentry event, the breadcrumb trail shows
UnknownError: Internal error opening backing store for indexedDB.open.occurring 200ms before theQuotaExceededError. Both errors in the same session, same user — strongly confirming they share the same root cause: LevelDB backing store in a corrupted state.Root Cause: Chromium Bug, Not Real Quota Exhaustion
Evidence summary
disk_fullflag comes fromleveldb_env::IndicatesDiskFull(status)— a heuristic on LevelDB's status code, not an actual disk space checkWhy the current eviction path works 99.997% of the time
Only 6 out of 234,697 occurrences exhausted all retries. Two hypotheses:
Can the heal mechanism (PR #780) help?
Not directly. Unlike backing store corruption where the problem is a stale cached
dbp, this error originates from Chrome's IDB infrastructure actively refusingindexedDB.open(). A fresh JS-levelindexedDB.open()call hits the same Chrome-level state. ThecacheOpenPromiserejection cleanup in #780 already prevents stale rejected promises from blocking subsequent operations, which is sufficient at thecreateStorelevel.However, the Fullstory data shows that the "full disk" error frequently co-occurs with or follows the backing store corruption error (#1) and connection closing error (#3) — both of which #780 does heal. Fixing those upstream errors may reduce the cascade into false "full disk" errors.
Key Takeaways
The "full disk" error is a symptom, not the disease. The real root cause is LevelDB backing store corruption in Chromium. The
QuotaExceededErroris a misclassified cascade error.The 234K monthly count is inflated. A single affected session generates 30-80+ error entries due to the infinite retry loop (~30s interval). The actual number of affected user-sessions is orders of magnitude smaller.
Silent data loss is the real impact. Users continue working while every write silently fails. The app looks functional (reads from memory cache) but nothing persists to IDB.
Existing infrastructure can help filter false positives. Onyx already calls
navigator.storage.estimate()viagetDatabaseSize()on every eviction — but only logs the result, never uses it for decision-making. The data consistently shows 0% usage for these errors. Using this signal to skip eviction and retry with a delay instead could avoid unnecessary data deletion.The infinite retry loop needs a circuit breaker. Once
"no acceptable keys to remove"fires for a given error, subsequent retries for the same root cause will also fail. A mechanism to stop retrying the same failing operation (or at least back off exponentially) would reduce log noise and wasted CPU.sosek108 commentedon Jun 1, 2026
Update posted here: #87873 (comment)
sosek108 commentedon Jun 3, 2026
Let's close this as duplicate of #87873 (comment)
cc: @Julesssss