microsoft/playwright · error · Error
Cannot transfer files larger than 50Mb to a browser not co-l
Error message
Cannot transfer files larger than 50Mb to a browser not co-located with the server
What it means
When the browser is not collocated with the Playwright server and localPaths are used, files are read into memory buffers to ship across the boundary. If their combined size meets or exceeds 50 MiB (fileUploadSizeLimit) the upload is refused to avoid exhausting memory.
Source
Thrown at packages/playwright-core/src/server/fileUploadUtils.ts:66
localDirectory = (directoryStream as WritableStreamDispatcher).path();
if (localPaths) {
for (const p of localPaths)
assert(path.isAbsolute(p) && path.resolve(p) === p, 'Paths provided to localPaths must be absolute and fully resolved.');
}
let fileBuffers: {
name: string,
mimeType?: string,
buffer: Buffer,
lastModifiedMs?: number,
}[] | undefined = payloads;
if (!frame._page.browserContext._browser._isBrowserCollocatedWithServer) {
// If the browser is on a different machine read files into buffers.
if (localPaths) {
if (await filesExceedUploadLimit(localPaths))
throw new Error('Cannot transfer files larger than 50Mb to a browser not co-located with the server');
fileBuffers = await Promise.all(localPaths.map(async item => {
return {
name: path.basename(item),
buffer: await fs.promises.readFile(item),
lastModifiedMs: (await fs.promises.stat(item)).mtimeMs,
};
}));
localPaths = undefined;
}
}
const filePayloads: types.FilePayload[] | undefined = fileBuffers?.map(payload => ({
name: payload.name,
mimeType: payload.mimeType || mime.getType(payload.name) || 'application/octet-stream',
buffer: payload.buffer.toString('base64'),
lastModifiedMs: payload.lastModifiedMs
}));
View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Switch to streaming uploads via a writable stream when available to avoid the in-memory cap.
- Reduce the per-call payload below 50 MiB (split into multiple calls or trim fixtures).
- Run the browser collocated with the server so the 50 MiB transfer limit does not apply.
- Compress or sample the test data so the fixture stays under the limit.
Example fix
// before: 60 MiB file against remote browser -> throws
await handle.setInputFiles('/data/big.mov');
// after: stream instead, or shrink fixture
await handle.setInputFiles('/data/small.mov'); Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const LIMIT = 50 * 1024 * 1024;
async function totalSize(paths: string[]) {
return (await Promise.all(paths.map(p => fs.promises.stat(p).then(s => s.size)))).reduce((a,b)=>a+b,0);
}
if (await totalSize(paths) >= LIMIT) throw new Error('over 50MiB'); Type guard
null
Try / catch
null
Prevention
- Keep test upload fixtures small (<50 MiB) when targeting a remote browser.
- Use streaming for legitimately large files.
When it happens
Trigger: Calling setInputFiles(paths) where the total size of all listed files is >= 50 MiB, while _isBrowserCollocatedWithServer is false (remote browser / separate browser server host). filesExceedUploadLimit sums fs.stat sizes.
Common situations: Uploading large media, PDFs, archives, or datasets in CI against a remote browser service; batch uploads of many files whose total crosses 50 MiB; test fixtures with oversized attachments.
Related errors
- localPaths are not allowed when the client is not local
- Path is not available when connecting remotely. Use saveAs()
- Route from har is not supported in thin clients
- Cannot set input files to detached element
- Multiple directories are not supported
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/8a6f65e95b7decf6.
Report an issue: GitHub.