← Debugging Guides

阅读中文版本

DOMException QuotaExceededError — Storage Full

Fix QuotaExceededError from localStorage and IndexedDB by measuring usage, evicting stale entries, and requesting persistent storage.

intermediatedebuggingbrowserstoragequota

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.