{"record":{"id":"559b49136c5fa1a6","repo":"microsoft/playwright","slug":"unable-to-serialize-opfs-e-message","errorCode":null,"errorMessage":"Unable to serialize OPFS: ${e.message}","messagePattern":"Unable to serialize OPFS: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/injected/src/storageScript.ts","lineNumber":187,"sourceCode":"    return collect(root, '');\n  }\n\n  async collect(record: { indexedDB: boolean, opfs: boolean }): Promise<SerializedStorage> {\n    const localStorage = Object.keys(this._global.localStorage).map(name => ({ name, value: this._global.localStorage.getItem(name)! }));\n    const result: SerializedStorage = { localStorage };\n    if (record.indexedDB) {\n      try {\n        const databases = await this._global.indexedDB.databases();\n        result.indexedDB = await Promise.all(databases.map(db => this._collectDB(db)));\n      } catch (e) {\n        throw new Error('Unable to serialize IndexedDB: ' + e.message);\n      }\n    }\n    if (record.opfs) {\n      try {\n        result.opfs = await this._collectOPFS(await this._global.navigator.storage.getDirectory());\n      } catch (e) {\n        throw new Error('Unable to serialize OPFS: ' + e.message);\n      }\n    }\n    return result;\n  }\n\n  private async _restoreDB(dbInfo: IndexedDBDatabase) {\n    const openRequest = this._global.indexedDB.open(dbInfo.name, dbInfo.version);\n    openRequest.addEventListener('upgradeneeded', () => {\n      const db = openRequest.result;\n      for (const store of dbInfo.stores) {\n        const objectStore = db.createObjectStore(store.name, { autoIncrement: store.autoIncrement, keyPath: store.keyPathArray ?? store.keyPath });\n        for (const index of store.indexes)\n          objectStore.createIndex(index.name, index.keyPathArray ?? index.keyPath!, { unique: index.unique, multiEntry: index.multiEntry });\n      }\n    });\n\n    // after `upgradeneeded` finishes, `success` event is fired.\n    const db = await this._idbRequestToPromise(openRequest);","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/microsoft/playwright/blob/312030cdcee20c006343e5f8420fe451b9aa6390/packages/injected/src/storageScript.ts#L169-L205","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst state = await context.storageState({ opfs: true }); // throws if OPFS unreadable\n// after\nlet state;\ntry {\n  state = await context.storageState({ opfs: true });\n} catch (e) {\n  if (String(e.message).startsWith('Unable to serialize OPFS:')) {\n    state = await context.storageState(); // fall back without OPFS\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"if (!page.url().startsWith('https://') && !page.url().startsWith('http://localhost')) {\n  // OPFS/File System Access API requires a secure context\n  console.warn('Skipping OPFS capture on insecure origin:', page.url());\n}","typeGuard":"function supportsOpfs(win: Window): boolean {\n  return !!win.navigator?.storage?.getDirectory;\n}","tryCatchPattern":"try {\n  const state = await context.storageState({ opfs: true });\n} catch (e) {\n  if (String(e.message).includes('Unable to serialize OPFS:')) {\n    const reason = String(e.message).replace('Unable to serialize OPFS: ', '');\n    console.error('OPFS capture failed:', reason);\n    // fall back to non-OPFS storage state\n  } else throw e;\n}","preventionTips":["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."],"tags":["storage-state","opfs","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"312030cdcee20c006343e5f8420fe451b9aa6390","analyzedAt":"2026-09-07T14:42:43.271Z","contentChangedAt":"2026-09-07T14:42:43.271Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}