Version
1.63.0 (matching bundled full Chromium 153.0.8010.12). The same script also reproduces with playwright-core 1.62.1 / Chromium 151.0.7922.34.
Steps to reproduce
Repository: https://github.com/etonedu2026/playwright-no-store-stream-repro
The repository must remain private under the account owner's policy; maintainers will not have access by default. I understand the template requests a repository. To make this report independently reproducible without access, the complete synthetic script and exact dependency are included below. It contains no application code or application data.
In an empty directory, save the following as package.json:
{
"name": "playwright-no-store-stream-repro",
"private": true,
"type": "module",
"devDependencies": { "playwright-core": "1.63.0" }
}
Save the following as repro.mjs:
import { createServer } from 'node:http';
import { chromium } from 'playwright-core';
const server = createServer((req, res) => {
const url = new URL(req.url, 'http://localhost');
if (url.pathname !== '/data') return res.end('<html>synthetic reproduction</html>');
res.writeHead(200, {
'Content-Type': 'application/json',
'Cache-Control': url.searchParams.get('cache'),
});
res.write('{"ok":');
setTimeout(() => res.end('true}'), 20);
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const origin = `http://127.0.0.1:${server.address().port}`;
const browser = await chromium.launch({ headless: true, executablePath: chromium.executablePath() });
const results = [];
try {
for (const [cache, reader] of [['no-store', 'stream'], ['no-store', 'json'], ['no-cache', 'stream']]) {
for (let repeat = 0; repeat < 2; repeat++) {
const context = await browser.newContext();
try {
const page = await context.newPage();
await page.goto(origin);
const matches = request => new URL(request.url()).pathname === '/data';
const terminal = new Promise(resolve => {
page.on('requestfinished', request => {
if (matches(request)) resolve({ event: 'requestfinished' });
});
page.on('requestfailed', request => {
if (matches(request)) resolve({ event: 'requestfailed', failure: request.failure()?.errorText });
});
});
const headers = page.waitForResponse(response => matches(response.request()));
const application = page.evaluate(async ({ cache, reader }) => {
const response = await fetch(`/data?cache=${cache}`);
if (reader === 'json') return (await response.json()).ok;
const handle = response.body.getReader();
const chunks = [];
while (true) {
const { done, value } = await handle.read();
if (done) break;
chunks.push(...value);
}
handle.releaseLock();
return JSON.parse(new TextDecoder().decode(new Uint8Array(chunks))).ok;
}, { cache, reader });
const response = await headers;
let hostBodyOk = false;
let hostError = null;
try { hostBodyOk = (await response.json()).ok === true; }
catch (error) {
hostError = error.message.includes('No data found for resource with given identifier')
? 'Network.getResponseBody: No data found for resource with given identifier'
: 'Other response body error';
}
results.push({ cache, reader, repeat, pageBodyOk: await application, hostBodyOk, hostError, terminal: await terminal });
} finally { await context.close(); }
}
}
console.log(JSON.stringify({ node: process.version, browser: browser.version(), results }, null, 2));
} finally {
await browser.close();
server.closeAllConnections();
await new Promise(resolve => server.close(resolve));
}
Run on Linux:
npm install --ignore-scripts --no-audit --no-fund --registry=https://registry.npmjs.org
export PLAYWRIGHT_BROWSERS_PATH="$(mktemp -d)"
npx playwright-core install chromium
timeout 30s node repro.mjs
The repository pins the same version and includes a lockfile, so a repository checkout can use npm ci.
Expected behavior
All six responses are completely consumed by the page. For each, Playwright should emit requestfinished, and host-side response.json() should return {"ok":true}.
Actual behavior
Both no-store + stream repetitions:
- Page reader reaches
done: true, parses all 11 bytes and returns ok: true.
- Playwright emits
requestfailed with net::ERR_ABORTED.
- Host
response.json() fails with Network.getResponseBody: No data found for resource with given identifier.
Both no-store + native response.json() controls and both no-cache + stream controls emit requestfinished and allow host body reading. The same six-case result was observed on both versions listed above.
The process exits 0 after printing the diagnostic results; exit 0 is not a passing assertion.
Additional context
This uses only a synthetic loopback Node HTTP server and Playwright. There is no AbortController, reader.cancel, request interception, response mocking, Service Worker, application framework, account or database. Each page/context is closed only after the page promise and original request terminal event have completed.
The server's 20 ms delay separates two writes; it is not a client-side sleep intended to fix or hide a failure. Full Chromium is launched using chromium.executablePath(). Changing to no-cache is only a diagnostic control, not a proposed workaround for sensitive responses that must retain no-store.
I have not established the upstream implementation cause or whether it belongs to Chromium or Playwright. No application workaround is being claimed.
Environment
Manually allowlisted environment fields (no environment-variable dump):
- OS: Ubuntu 26.04 LTS, Linux x86_64 under WSL2
- Kernel: 6.18.33.1-microsoft-standard-WSL2
- Node: 22.23.2
- npm: 10.9.8
- playwright-core: 1.63.0, exact npm dependency
- Browser: bundled Chromium 153.0.8010.12, headless, full executable
Version
1.63.0 (matching bundled full Chromium 153.0.8010.12). The same script also reproduces with playwright-core 1.62.1 / Chromium 151.0.7922.34.
Steps to reproduce
Repository: https://github.com/etonedu2026/playwright-no-store-stream-repro
The repository must remain private under the account owner's policy; maintainers will not have access by default. I understand the template requests a repository. To make this report independently reproducible without access, the complete synthetic script and exact dependency are included below. It contains no application code or application data.
In an empty directory, save the following as
package.json:{ "name": "playwright-no-store-stream-repro", "private": true, "type": "module", "devDependencies": { "playwright-core": "1.63.0" } }Save the following as
repro.mjs:Run on Linux:
The repository pins the same version and includes a lockfile, so a repository checkout can use
npm ci.Expected behavior
All six responses are completely consumed by the page. For each, Playwright should emit
requestfinished, and host-sideresponse.json()should return{"ok":true}.Actual behavior
Both
no-store + streamrepetitions:done: true, parses all 11 bytes and returnsok: true.requestfailedwithnet::ERR_ABORTED.response.json()fails withNetwork.getResponseBody: No data found for resource with given identifier.Both
no-store + native response.json()controls and bothno-cache + streamcontrols emitrequestfinishedand allow host body reading. The same six-case result was observed on both versions listed above.The process exits 0 after printing the diagnostic results; exit 0 is not a passing assertion.
Additional context
This uses only a synthetic loopback Node HTTP server and Playwright. There is no AbortController, reader.cancel, request interception, response mocking, Service Worker, application framework, account or database. Each page/context is closed only after the page promise and original request terminal event have completed.
The server's 20 ms delay separates two writes; it is not a client-side sleep intended to fix or hide a failure. Full Chromium is launched using
chromium.executablePath(). Changing tono-cacheis only a diagnostic control, not a proposed workaround for sensitive responses that must retainno-store.I have not established the upstream implementation cause or whether it belongs to Chromium or Playwright. No application workaround is being claimed.
Environment
Manually allowlisted environment fields (no environment-variable dump):