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

  1. Pass only the arguments the Web API actually accepts (MutationObserver takes 1 callback, FileReader takes 0, IntersectionObserver at most 2).
  2. If spreading an array, slice it to the documented arity: new MutationObserver(...args.slice(0, 1)).
  3. 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

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


AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22). Data as JSON: /api/errors/cb9cfe03cc616248. Report an issue: GitHub.