microsoft/playwright · error · Error
serializedArgs is not an array. This can happen when Array.p
Error message
serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly
What it means
Thrown by PageBinding.dispatch when the binding payload's serializedArgs field is not an Array. Playwright serializes binding arguments through JSON; if page-side code overrode Array.prototype.toJSON (or similar) the serialized value is no longer a JSON array and cannot be spread into the callback, so dispatch aborts with a hint pointing at the likely culprit.
Source
Thrown at packages/playwright-core/src/server/page.ts:1086
forClient?: unknown;
constructor(parent: BrowserContext | Page, name: string, playwrightFunction: frames.FunctionWithSource, noGlobal?: boolean) {
super(parent);
this.name = name;
this.playwrightFunction = playwrightFunction;
this.initScript = new InitScript(parent, `globalThis['${kBindingsControllerProperty}'].addBinding(${JSON.stringify(name)}, ${!!noGlobal})`);
this.cleanupScript = `globalThis['${kBindingsControllerProperty}'].removeBinding(${JSON.stringify(name)})`;
}
static async dispatch(page: Page, payload: string, context: dom.FrameExecutionContext) {
const { name, seq, serializedArgs } = JSON.parse(payload) as BindingPayload;
try {
assert(context.world);
const binding = page.getBinding(name);
if (!binding)
throw new Error(`Function "${name}" is not exposed`);
if (!Array.isArray(serializedArgs))
throw new Error(`serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly`);
const args = serializedArgs.map(a => parseEvaluationResultValue(a));
const result = await binding.playwrightFunction({ frame: context.frame, page, context: page.browserContext }, ...args);
context.evaluateExpressionHandle(`arg => globalThis['${kBindingsControllerProperty}'].deliverBindingResult(arg)`, { isFunction: true }, { name, seq, result }).catch(e => debugLogger.log('error', e));
} catch (error) {
context.evaluateExpressionHandle(`arg => globalThis['${kBindingsControllerProperty}'].deliverBindingResult(arg)`, { isFunction: true }, { name, seq, error }).catch(e => debugLogger.log('error', e));
}
}
override async dispose(): Promise<void> {
await this.parent.removeExposedBinding(this);
}
}
export class InitScript extends DisposableObject {
readonly source: string;
constructor(owner: BrowserContext | Page, source: string) {
super(owner);View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Find and remove the Array.prototype.toJSON override (or any Array prototype mutation) in the page or its loaded scripts.
- If a library requires the override, scope it so it does not run during binding serialization, or delete Array.prototype.toJSON before invoking the exposed function.
- Pass primitive/plain-object arguments to exposed functions and avoid relying on custom toJSON on collections.
Example fix
// page-side culprit
Array.prototype.toJSON = function() { return [...this]; }; // breaks serialization
// fix
await page.evaluate(() => { delete (Array.prototype as any).toJSON; });
await page.evaluate(() => window.cb(1, 2, 3)); Defensive patterns
Strategy: validation
Validate before calling
// Strip known prototype pollution before exercising bindings
await page.addInitScript(() => {
delete (Array.prototype as any).toJSON;
delete (Object.prototype as any).toJSON;
}); Prevention
- Audit page-loaded scripts for Array.prototype/Object.prototype mutations.
- Remove legacy toJSON polyfills that target obsolete browsers.
- Use addInitScript to neutralize prototype overrides before app code runs.
When it happens
Trigger: The page under test (or a third-party script it loads) defines Array.prototype.toJSON, mutating how arrays serialize; a loaded library patches Array.prototype before the binding call; the payload is constructed/forwarded by custom code that does not pass a real array.
Common situations: Legacy libraries that polyfill toJSON on Array for older IE compatibility; test pages that include legacy prototype extensions; monkeypatched globals in the page environment.
Related errors
- Function "${name}" has been already registered
- Function "${name}" has been already registered in the browse
- Function "${name}" is not exposed
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/afc0d92be7fec803.
Report an issue: GitHub.