angular/angular · warning · Error
Arg list too long.
Error message
Arg list too long.
What it means
Thrown by zone.js patchClass's patched constructor wrapper (utils.ts:348). zone.js wraps browser classes (MutationObserver, IntersectionObserver, FileReader, WebKitMutationObserver) so instances are created inside the current zone, but the wrapper only forwards up to 4 constructor arguments; a 5th or later argument triggers this guard.
Source
Thrown at packages/zone.js/lib/common/utils.ts:348
const a = bindArguments(<any>arguments, className);
switch (a.length) {
case 0:
this[originalInstanceKey] = new OriginalClass();
break;
case 1:
this[originalInstanceKey] = new OriginalClass(a[0]);
break;
case 2:
this[originalInstanceKey] = new OriginalClass(a[0], a[1]);
break;
case 3:
this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2]);
break;
case 4:
this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2], a[3]);
break;
default:
throw new Error('Arg list too long.');
}
};
// attach original delegate to patched function
attachOriginToPatched(_global[className], OriginalClass);
const instance = new OriginalClass(function () {});
let prop;
for (prop in instance) {
// https://bugs.webkit.org/show_bug.cgi?id=44721
if (className === 'XMLHttpRequest' && prop === 'responseBlob') continue;
(function (prop) {
if (typeof instance[prop] === 'function') {
_global[className].prototype[prop] = function () {
return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments);
};
} else {View on GitHub (pinned to 51cb07e980)
Solutions
- Pass only the arguments the Web API actually accepts (MutationObserver takes 1 callback, FileReader takes 0, IntersectionObserver at most 2).
- If spreading an array, slice it to the documented arity: new MutationObserver(...args.slice(0, 1)).
- Audit dynamic constructors invoked via window[className] patterns.
Example fix
// before new (window['MutationObserver'])(...collectedArgs); // collectedArgs.length may exceed 4 // after new MutationObserver(collectedArgs[0]); // pass exactly the documented callback
Defensive patterns
Strategy: validation
Validate before calling
// Clamp dynamic constructor args to the API's real arity
const ARITY: Record<string, number> = {MutationObserver: 1, IntersectionObserver: 2, FileReader: 0};
function constructObserver(name: keyof typeof ARITY, args: any[]) {
const Ctor = (window as any)[name];
return new Ctor(...args.slice(0, ARITY[name]));
} Type guard
function withinZonePatchLimit(args: unknown[]): boolean { return args.length <= 4; } Try / catch
try { obs = new MutationObserver(...args); } catch (e: any) { if (/Arg list too long/.test(e.message)) { obs = new MutationObserver(args[0]); } else throw e; } Prevention
- Pass only documented constructor arguments to browser observer classes.
- Avoid spreading unbounded arrays into constructors.
When it happens
Trigger: Calling new MutationObserver(...)/FileReader()/IntersectionObserver(...) with 5 or more arguments — essentially always a bug in caller code (these APIs take 0-2 args), e.g. spreading an unbounded array into the constructor.
Common situations: Code doing new (window[someClass])(...args) with a dynamic args array that can exceed 4 elements; test harnesses passing extra config arguments to polyfilled observers.
Related errors
- Tried too often to get the ending mark: ${loopCount}
- can capture frames only once per benchmark run
- Cannot assign to read only property '${prop}' of ${obj}
- Promise resolved with itself
- Uncaught (in promise): ${readableObjectToString(value)}${val
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/cb9cfe03cc616248.
Report an issue: GitHub.