actualbudget/actual · warning

Persistent storage request failed:

Error message

Persistent storage request failed:

What it means

A console.warn emitted in packages/desktop-client/src/browser-preload.js when the navigator.storage.persist() promise rejects. The browser refused or failed the persistent-storage request, meaning local budget data (IndexedDB/OPFS) may be evicted under storage pressure. It is logged, not thrown — the app continues without persistence guarantees.

Source

Thrown at packages/desktop-client/src/browser-preload.js:76

    isOpenIdCallback,
});

// Ask the browser to exclude this origin's storage (the local budget database
// in IndexedDB) from automatic eviction under storage pressure. Without this,
// the browser is allowed to silently delete all local data, forcing a full
// re-download of the budget and losing any changes not yet synced.
if (navigator.storage?.persist) {
  void navigator.storage
    .persist()
    .then(persisted => {
      if (!persisted) {
        console.warn(
          'Persistent storage was not granted; the browser may evict local budget data under storage pressure.',
        );
      }
    })
    .catch(error => {
      console.warn('Persistent storage request failed:', error);
    });
}

let isUpdateReadyForDownload = false;
let markUpdateReadyForDownload;
const isUpdateReadyForDownloadPromise = new Promise(resolve => {
  markUpdateReadyForDownload = () => {
    isUpdateReadyForDownload = true;
    resolve(true);
  };
});
// Skip SW registration in dev so stale cached assets don't override edits
// between page loads. Plugin code that needs a SW can register one itself.
// In dev there is no SW to install, so applyAppUpdate() can't rely on the
// SW lifecycle to swap the page — fall back to a plain reload so callers
// don't hang on the never-resolving promise inside applyAppUpdate.
const updateSW = IS_DEV
  ? () => window.location.reload()

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Serve the app over HTTPS so StorageManager APIs are available
  2. Update to a modern browser that supports navigator.storage.persist()
  3. Check storage.persisted() and warn users to install the app / export budgets regularly
  4. Accept degraded behavior — data may be evicted under disk pressure; enable regular backups

Example fix

// before
if (!isSecureContext) { /* API missing, warns every load */ }
// after
if ('storage' in navigator && typeof navigator.storage.persist === 'function') {
  await navigator.storage.persist();
}
Defensive patterns

Strategy: fallback

Validate before calling

const canPersist = 'storage' in navigator && typeof navigator.storage.persist === 'function';

Prevention

When it happens

Trigger: Calling navigator.storage.persist() during web app boot and the promise rejecting — typically only in browsers lacking the StorageManager API or when the call is rejected outright (as opposed to resolving to false).

Common situations: Running Actual in an embedded/older browser without StorageManager; insecure (non-HTTPS) origins where the API may be unavailable; privacy modes blocking storage APIs; Safari Private Browsing.

Related errors


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/5dfbb097ec0f7d51. Report an issue: GitHub.