microsoft/playwright · error · Error
Unable to serialize OPFS: ${e.message}
Error message
Unable to serialize OPFS: ${e.message} What it means
During storage-state collection, Playwright gathers the Origin Private File System (OPFS) contents of a page so they can be captured into storageState. If enumerating or reading the OPFS directory fails for any reason, the code in `collect` wraps the underlying error and rethrows it with this prefix so the caller knows serialization of browser storage failed. The original failure reason is preserved in the message suffix.
Source
Thrown at packages/injected/src/storageScript.ts:187
return collect(root, '');
}
async collect(record: { indexedDB: boolean, opfs: boolean }): Promise<SerializedStorage> {
const localStorage = Object.keys(this._global.localStorage).map(name => ({ name, value: this._global.localStorage.getItem(name)! }));
const result: SerializedStorage = { localStorage };
if (record.indexedDB) {
try {
const databases = await this._global.indexedDB.databases();
result.indexedDB = await Promise.all(databases.map(db => this._collectDB(db)));
} catch (e) {
throw new Error('Unable to serialize IndexedDB: ' + e.message);
}
}
if (record.opfs) {
try {
result.opfs = await this._collectOPFS(await this._global.navigator.storage.getDirectory());
} catch (e) {
throw new Error('Unable to serialize OPFS: ' + e.message);
}
}
return result;
}
private async _restoreDB(dbInfo: IndexedDBDatabase) {
const openRequest = this._global.indexedDB.open(dbInfo.name, dbInfo.version);
openRequest.addEventListener('upgradeneeded', () => {
const db = openRequest.result;
for (const store of dbInfo.stores) {
const objectStore = db.createObjectStore(store.name, { autoIncrement: store.autoIncrement, keyPath: store.keyPathArray ?? store.keyPath });
for (const index of store.indexes)
objectStore.createIndex(index.name, index.keyPathArray ?? index.keyPath!, { unique: index.unique, multiEntry: index.multiEntry });
}
});
// after `upgradeneeded` finishes, `success` event is fired.
const db = await this._idbRequestToPromise(openRequest);View on GitHub (pinned to 312030cdce)
Solutions
- Read the underlying `e.message` after the prefix to identify the actual OPFS failure and fix that root cause.
- Ensure the page origin is a secure context (https:// or localhost) where `navigator.storage` is fully functional.
- Verify the browser context is not blocking storage (check context permissions / storage partitioning settings).
- Avoid mutating or navigating the page concurrently while storageState collection runs.
- If OPFS capture is not needed, disable OPFS recording so `record.opfs` is not set.
Example fix
// before
const state = await context.storageState({ opfs: true }); // throws if OPFS unreadable
// after
let state;
try {
state = await context.storageState({ opfs: true });
} catch (e) {
if (String(e.message).startsWith('Unable to serialize OPFS:')) {
state = await context.storageState(); // fall back without OPFS
} else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!page.url().startsWith('https://') && !page.url().startsWith('http://localhost')) {
// OPFS/File System Access API requires a secure context
console.warn('Skipping OPFS capture on insecure origin:', page.url());
} Type guard
function supportsOpfs(win: Window): boolean {
return !!win.navigator?.storage?.getDirectory;
} Try / catch
try {
const state = await context.storageState({ opfs: true });
} catch (e) {
if (String(e.message).includes('Unable to serialize OPFS:')) {
const reason = String(e.message).replace('Unable to serialize OPFS: ', '');
console.error('OPFS capture failed:', reason);
// fall back to non-OPFS storage state
} else throw e;
} Prevention
- Only enable OPFS recording on secure-context origins.
- Do not navigate or mutate the page while storageState collection is running.
- Pin a browser build with full File System Access support when capturing OPFS.
- Check context storage permissions before capture in restricted environments.
When it happens
Trigger: A page that has `record.opfs` set (storageState collection with OPFS enabled) calls `navigator.storage.getDirectory()` and `_collectOPFS`, and either getting the directory handle or walking/reading OPFS files throws — e.g. the page is on an insecure origin, storage is partitioned/blocked, a file was deleted mid-read, or a File System Access API operation rejects.
Common situations: Running storageState capture against a page whose origin blocks persistent storage (private/incognito-like contexts, Safari ITP, cross-origin iframes with partitioned storage), or a race where OPFS entries vanish between listing and reading during parallel test teardown.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Unable to restore OPFS: ${e.message}
- Cannot serialize result: object reference chain is too long.
- Cannot serialize result: object reference chain is too long.
- Passed function is not well-serializable!
- Cannot serialize result: object reference chain is too long.
AI-assisted analysis of microsoft/playwright@312030cdce (2026-09-07).
Data as JSON: /api/errors/559b49136c5fa1a6.
Report an issue: GitHub.