{"record":{"id":"2923d0835efbfa32","repo":"microsoft/playwright","slug":"kcoveragestasherror-error","errorCode":null,"errorMessage":"kCoverageStashError + ': ' + error","messagePattern":"kCoverageStashError \\+ ': ' \\+ error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/injected/src/coverageScript.ts","lineNumber":120,"sourceCode":"}\n\nfunction stashErrorKey(sessionId: string) {\n  return kCoverageStashPrefix + 'error.' + sessionId;\n}\n\n// Stashes of other sessions are stale, e.g. left by a previous run in a persistent profile.\nexport function takeCoverageStashes(global: typeof globalThis, sessionId: string): string[] {\n  const result: string[] = [];\n  let storage: Storage;\n  try {\n    storage = global.localStorage;\n  } catch {\n    return result;\n  }\n  const error = storage.getItem(stashErrorKey(sessionId));\n  if (error) {\n    storage.removeItem(stashErrorKey(sessionId));\n    throw new Error(kCoverageStashError + ': ' + error);\n  }\n  const sessionPrefix = kCoverageStashPrefix + sessionId + '.';\n  const keys: string[] = [];\n  for (let i = 0; i < storage.length; i++) {\n    const key = storage.key(i);\n    if (key && key.startsWith(kCoverageStashPrefix))\n      keys.push(key);\n  }\n  for (const key of keys) {\n    const json = key.startsWith(sessionPrefix) ? storage.getItem(key) : undefined;\n    storage.removeItem(key);\n    if (json)\n      result.push(json);\n  }\n  return result;\n}\n","sourceCodeStart":102,"sourceCodeEnd":137,"githubUrl":"https://github.com/microsoft/playwright/blob/f1d33b5029be8bbc1095fe88e559117fa3a6243b/packages/injected/src/coverageScript.ts#L102-L137","documentation":"Playwright's coverage integration stashes per-session coverage data in browser localStorage and transfers it to the test runner. If the in-page script hit an error while collecting coverage, it records the message under a stash-error key; takeCoverageStashes then reads, removes, and re-throws it on the Node side wrapped with the kCoverageStashError prefix so page-side coverage failures surface instead of being silently dropped.","triggerScenarios":"Calling takeCoverageStashes (via the coverage/chunks integration) when the browser page's injected coverage script previously stored an error string under stashErrorKey(sessionId) in localStorage.","commonSituations":"App code clears or rewrites localStorage during the test (logout handlers, storage migrations) and clobbers coverage stash entries; multiple contexts sharing an origin collide on stash keys; the in-page collector throws on unusual script content.","solutions":["Read the text after the coverage-stash-error prefix — it is the original in-page error — and fix the underlying page-side coverage failure it reports.","Stop the application from clearing/rewriting all localStorage during tests while coverage is active.","Reproduce with coverage disabled to confirm the failure is coverage-specific, then narrow to the offending script.","Upgrade Playwright — stash-key handling has changed between versions."],"exampleFix":"// before (app code under test)\nwindow.addEventListener('unload', () => localStorage.clear());\n// after\nwindow.addEventListener('unload', () => {\n  Object.keys(localStorage)\n    .filter(k => !k.startsWith('__playwright_coverage_stash'))\n    .forEach(k => localStorage.removeItem(k));\n});","handlingStrategy":"try-catch","validationCode":"// Before running coverage-dependent assertions:\nconst errKey = Object.keys(localStorage).find(k => k.includes('coverage') && k.includes('error'));\nif (errKey) console.warn('Pending coverage stash error:', localStorage.getItem(errKey));","typeGuard":"function hasCoverageStashError(storage: Storage, sessionId: string): boolean {\n  return storage.getItem(`coverage-stash-error-${sessionId}`) !== null;\n}","tryCatchPattern":"let coverage;\ntry {\n  coverage = await takeCoverageStashes(sessionIds);\n} catch (e) {\n  console.warn('Coverage collection failed; continuing without it:', (e as Error).message);\n  coverage = null;\n}","preventionTips":["Do not clear or overwrite all localStorage in app code during tests while coverage is enabled.","Investigate the inner message after the prefix immediately — it identifies the real page-side failure.","Smoke-test coverage collection in isolation before enabling it in CI.","Keep Playwright and app/gallery bundles in sync to avoid collector incompatibilities."],"tags":["coverage","browser","storage"],"backgroundTag":"unexpected-response-shape","analyzedSha":"f1d33b5029be8bbc1095fe88e559117fa3a6243b","analyzedAt":"2026-09-21T21:58:31.278Z","contentChangedAt":"2026-09-21T21:58:31.278Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}