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
- Inspect the message suffix for the underlying OPFS write failure (quota, security, unsupported).
- Re-capture the storageState with the same browser engine/version that will restore it.
- Free storage quota or increase the context/browser storage quota in constrained CI environments.
- Restore on a secure origin (https/localhost) where the File System Access API is available.
- 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
- Capture and restore storageState with the same browser engine and version.
- Strip `opfs` entries when the target environment cannot replay them.
- Ensure CI containers have enough storage quota before restoring OPFS state.
- Only restore on secure-context pages.
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.