microsoft/playwright · error · Error

Unable to restore OPFS: ${e.message}

Error message

Unable to restore OPFS: ${e.message}

What it means

When restoring a saved storageState into a new context, Playwright writes back cookies, localStorage, IndexedDB and OPFS files. If `_restoreOPFS` throws — recreating the captured OPFS files fails — `restore` rethrows it as 'Unable to restore OPFS: <reason>'. The suffix contains the underlying error so developers can diagnose why the OPFS replay failed.

Source

Thrown at packages/injected/src/storageScript.ts:307

      for (const db of await this._global.indexedDB.databases?.() || []) {
        // Do not wait for the callback - it is called on timer in Chromium (slow).
        if (db.name)
          this._global.indexedDB.deleteDatabase(db.name!);
      }
      await Promise.all((originState?.indexedDB ?? []).map(dbInfo => this._restoreDB(dbInfo)));
    } catch (e) {
      throw new Error('Unable to restore IndexedDB: ' + e.message);
    }

    this._global.sessionStorage.clear();
    this._global.localStorage.clear();
    for (const { name, value } of (originState?.localStorage || []))
      this._global.localStorage.setItem(name, value);

    try {
      await this._restoreOPFS(originState);
    } catch (e) {
      throw new Error('Unable to restore OPFS: ' + e.message);
    }
  }
}

View on GitHub (pinned to 312030cdce)

Solutions

  1. Inspect the message suffix for the underlying OPFS write failure (quota, security, unsupported).
  2. Re-capture the storageState with the same browser engine/version that will restore it.
  3. Free storage quota or increase the context/browser storage quota in constrained CI environments.
  4. Restore on a secure origin (https/localhost) where the File System Access API is available.
  5. Strip the `opfs` entries from the storageState JSON if OPFS replay is not required.

Example fix

// before
const context = await browser.newContext({ storageState: 'state.json' }); // throws restoring opfs
// after
const state = JSON.parse(fs.readFileSync('state.json', 'utf8'));
delete state.opfs; // skip OPFS replay if not needed
const context = await browser.newContext({ storageState: state });
Defensive patterns

Strategy: fallback

Validate before calling

const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
if (state.opfs?.length && !isSecureContextTarget) {
  delete state.opfs; // target cannot restore OPFS
}

Type guard

function isRestorableState(state: unknown): state is { origins?: unknown[]; cookies?: unknown[]; opfs?: unknown[] } {
  return typeof state === 'object' && state !== null;
}

Try / catch

try {
  const context = await browser.newContext({ storageState: stateFile });
} catch (e) {
  if (String(e.message).includes('Unable to restore OPFS:')) {
    console.error('OPFS restore failed:', String(e.message).replace('Unable to restore OPFS: ', ''));
    const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
    delete state.opfs;
    return browser.newContext({ storageState: state });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling an API that applies storageState (e.g. creating a context with `storageState`, or `context.storageState(...)` restore flows) where the saved state contains OPFS entries and writing those files back into `navigator.storage.getDirectory()` rejects — quota exceeded, insecure origin, unsupported browser build, or corrupted/malformed saved state.

Common situations: Reusing a storageState JSON captured in one browser on another browser/engine that lacks full OPFS support; quota exhaustion in CI containers with small tmpfs; manually edited or version-mismatched storageState files.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of microsoft/playwright@312030cdce (2026-09-07). Data as JSON: /api/errors/1b617e425fbfee5b. Report an issue: GitHub.