microsoft/playwright · error · Error
Exactly one of payloads, localPaths and streams must be prov
Error message
Exactly one of payloads, localPaths and streams must be provided
What it means
prepareFilesForUpload requires exactly one source of input files. It counts the truthy values among payloads, localPaths, localDirectory, streams, and directoryStream and throws if the count is not exactly 1 - i.e. zero provided or more than one provided at once.
Source
Thrown at packages/playwright-core/src/server/fileUploadUtils.ts:43
import type * as types from './types';
import type * as channels from './channels';
// Keep in sync with the client.
export const fileUploadSizeLimit = 50 * 1024 * 1024;
async function filesExceedUploadLimit(files: string[]) {
const sizes = await Promise.all(files.map(async file => (await fs.promises.stat(file)).size));
return sizes.reduce((total, size) => total + size, 0) >= fileUploadSizeLimit;
}
export async function prepareFilesForUpload(frame: Frame, params: Omit<channels.ElementHandleSetInputFilesParams, 'timeout'>): Promise<InputFilesItems> {
const { payloads, streams, directoryStream } = params;
let { localPaths, localDirectory } = params;
if (localPaths && !frame.attribution.playwright.options.isClientCollocatedWithServer)
throw new Error('localPaths are not allowed when the client is not local');
if ([payloads, localPaths, localDirectory, streams, directoryStream].filter(Boolean).length !== 1)
throw new Error('Exactly one of payloads, localPaths and streams must be provided');
if (streams)
localPaths = streams.map(c => (c as WritableStreamDispatcher).path());
if (directoryStream)
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;
View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Pass exactly one source: a single paths array, OR a single payloads array, OR a single directory.
- Clear stale fields when refactoring from one input mode to another.
- If clearing files is the goal, use setInputFiles([]) explicitly via the dedicated path rather than ambiguous params.
Example fix
// before
await handle.setInputFiles(); // nothing -> throws
// after: pick exactly one
await handle.setInputFiles(['/abs/file.pdf']);
// or
await handle.setInputFiles([{ name: 'f.pdf', mimeType: 'application/pdf', buffer }]); Defensive patterns
Strategy: validation
Validate before calling
// Enforce exactly-one before calling
function oneOf<T>(...vals: (T | undefined)[]): boolean {
return vals.filter(v => v !== undefined && v !== null).length === 1;
}
if (!oneOf(paths, payloads)) throw new Error('specify exactly one source'); Type guard
null
Try / catch
null
Prevention
- Treat the input sources as an enum; never combine them.
- Add a wrapper that asserts the cardinality once.
When it happens
Trigger: Calling setInputFiles with no arguments, with multiple mutually-exclusive source types at once, or with an empty/undefined combination. Also reached internally if a dispatcher forwards two populated fields.
Common situations: Migrating between path-based and payload-based uploads and accidentally leaving both; calling setInputFiles() with an empty array; passing both streams and payloads in a custom integration.
Related errors
- Multiple directories are not supported
- File paths must be all files or a single directory
- File paths cannot be mixed with buffers
- Cannot set buffer larger than 50Mb, please write it to a fil
- localPaths are not allowed when the client is not local
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/3c696787865b6125.
Report an issue: GitHub.