microsoft/playwright · error
kCoverageStashError + ': ' + error
Error message
kCoverageStashError + ': ' + error
What it means
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.
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.
Example fix
// before (app code under test)
window.addEventListener('unload', () => localStorage.clear());
// after
window.addEventListener('unload', () => {
Object.keys(localStorage)
.filter(k => !k.startsWith('__playwright_coverage_stash'))
.forEach(k => localStorage.removeItem(k));
}); Defensive patterns
Strategy: try-catch
Validate before calling
// Before running coverage-dependent assertions:
const errKey = Object.keys(localStorage).find(k => k.includes('coverage') && k.includes('error'));
if (errKey) console.warn('Pending coverage stash error:', localStorage.getItem(errKey)); Type guard
function hasCoverageStashError(storage: Storage, sessionId: string): boolean {
return storage.getItem(`coverage-stash-error-${sessionId}`) !== null;
} Try / catch
let coverage;
try {
coverage = await takeCoverageStashes(sessionIds);
} catch (e) {
console.warn('Coverage collection failed; continuing without it:', (e as Error).message);
coverage = null;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- CDP session is only available in Chromium
- page: expected Page or Frame
- Playwright Extension not found in
- The gallery page does not define window.mount().
- Tracing is only available in Chromium
AI-assisted analysis of microsoft/playwright@f1d33b5029 (2026-09-21).
Data as JSON: /api/errors/2923d0835efbfa32.
Report an issue: GitHub.
Appendix: source
Thrown at packages/injected/src/coverageScript.ts:120
}
function stashErrorKey(sessionId: string) {
return kCoverageStashPrefix + 'error.' + sessionId;
}
// Stashes of other sessions are stale, e.g. left by a previous run in a persistent profile.
export function takeCoverageStashes(global: typeof globalThis, sessionId: string): string[] {
const result: string[] = [];
let storage: Storage;
try {
storage = global.localStorage;
} catch {
return result;
}
const error = storage.getItem(stashErrorKey(sessionId));
if (error) {
storage.removeItem(stashErrorKey(sessionId));
throw new Error(kCoverageStashError + ': ' + error);
}
const sessionPrefix = kCoverageStashPrefix + sessionId + '.';
const keys: string[] = [];
for (let i = 0; i < storage.length; i++) {
const key = storage.key(i);
if (key && key.startsWith(kCoverageStashPrefix))
keys.push(key);
}
for (const key of keys) {
const json = key.startsWith(sessionPrefix) ? storage.getItem(key) : undefined;
storage.removeItem(key);
if (json)
result.push(json);
}
return result;
}
View on GitHub (pinned to f1d33b5029)