DOMException QuotaExceededError — Storage Full
Fix QuotaExceededError from localStorage and IndexedDB by measuring usage, evicting stale entries, and requesting persistent storage.
Symptoms
- DOMException: Failed to execute 'setItem' on 'Storage': Setting the value exceeded the quota
- localStorage writes succeed then suddenly throw
- IndexedDB transactions abort with QuotaExceededError
Possible causes
- The origin storage bucket is full (localStorage is roughly 5MB per origin)
- An oversized value such as a base64 image is stored directly
- In private mode some browsers cap storage sharply
Diagnosis steps
Measure current usage
console.log(JSON.stringify(localStorage).length)Interpretation
Approximates bytes used; compare with the roughly 5MB limit to confirm saturation.
Probe available space with navigator.storage
await navigator.storage.estimate()Interpretation
Returns usage and quota, showing how close the origin is to its limit.
Root cause
Each origin receives a storage quota. localStorage, sessionStorage, and IndexedDB share it, and exceeding the limit causes writes to throw QuotaExceededError rather than silently truncating data.
Fix
Store only what you must, keep large blobs in IndexedDB or on the server, evict stale entries by LRU, and call navigator.storage.persist() to reduce surprise eviction.
Risk note
Silently failing over to memory loses data on reload; always surface or handle the quota error.
Verify the fix
Write until the limit and confirm your eviction prevents the throw; check navigator.storage.estimate reports usage below quota.
Symptoms
This guide profiles the failure behind “DOMException QuotaExceededError — Storage Full”. It walks through the observable symptoms, a reproducible diagnosis path, the underlying root cause, the concrete fix, and how to verify the change and prevent a regression.
Observed symptoms include:
- DOMException: Failed to execute ‘setItem’ on ‘Storage’: Setting the value exceeded the quota
- localStorage writes succeed then suddenly throw
- IndexedDB transactions abort with QuotaExceededError
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Measure current usage
console.log(JSON.stringify(localStorage).length)
Approximates bytes used; compare with the roughly 5MB limit to confirm saturation.
Step 2: Probe available space with navigator.storage
await navigator.storage.estimate()
Returns usage and quota, showing how close the origin is to its limit.
Likely contributors, in order of frequency:
- The origin storage bucket is full (localStorage is roughly 5MB per origin)
- An oversized value such as a base64 image is stored directly
- In private mode some browsers cap storage sharply
Root Cause
Each origin receives a storage quota. localStorage, sessionStorage, and IndexedDB share it, and exceeding the limit causes writes to throw QuotaExceededError rather than silently truncating data.
The Fix
Store only what you must, keep large blobs in IndexedDB or on the server, evict stale entries by LRU, and call navigator.storage.persist() to reduce surprise eviction.
Watch out: Silently failing over to memory loses data on reload; always surface or handle the quota error.
async function safeSet(key, value) {
try {
localStorage.setItem(key, value);
} catch (err) {
if (err.name === 'QuotaExceededError' || err.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
evictOldest(); // drop stale keys, then retry once
localStorage.setItem(key, value);
} else throw err;
}
}
// prefer persistent storage to avoid surprise eviction
if (navigator.storage?.persist) await navigator.storage.persist();
Verify and Prevent
Write until the limit and confirm your eviction prevents the throw; check navigator.storage.estimate reports usage below quota.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.