mozilla/pdf.js · error · TypeError

Second argument of app.setTimeOut must be a number

Error message

Second argument of app.setTimeOut must be a number

What it means

`app.setTimeOut` is the Acrobat-JavaScript API for scheduling a script string to run after a delay. PDF.js's scripting sandbox validates the delay (`nMilliseconds`) is a `number` before forwarding it to the host's `setTimeout`. It throws a `TypeError` (not a generic Error) because the underlying timer requires a numeric delay and silent coercion would mask script bugs. The method also accepts a single labeled-object argument `{cExpr, nMilliseconds}`, in which case a missing delay defaults to 0.

Source

Thrown at src/scripting_api/app.js:637

        "Second argument of app.setInterval must be a number"
      );
    }
    const callbackId = this._registerTimeoutCallback(cExpr);
    this._externalCall("setInterval", [callbackId, nMilliseconds]);
    return this._registerTimeout(callbackId, true);
  }

  setTimeOut(cExpr, nMilliseconds = 0) {
    if (cExpr && typeof cExpr === "object") {
      nMilliseconds = cExpr.nMilliseconds || 0;
      cExpr = cExpr.cExpr;
    }

    if (typeof cExpr !== "string") {
      throw new TypeError("First argument of app.setTimeOut must be a string");
    }
    if (typeof nMilliseconds !== "number") {
      throw new TypeError("Second argument of app.setTimeOut must be a number");
    }
    const callbackId = this._registerTimeoutCallback(cExpr);
    this._externalCall("setTimeout", [callbackId, nMilliseconds]);
    return this._registerTimeout(callbackId, false);
  }

  trustedFunction() {
    /* Not implemented */
  }

  trustPropagatorFunction() {
    /* Not implemented */
  }
}

export { App };

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Pass a numeric literal or coerce first: `app.setTimeOut("fn()", Number(value))`.
  2. If the value comes from a field, coerce at the source: `const ms = Number(this.getField("delay").value) || 0;`.
  3. Use the labeled-object form which safely defaults a missing delay: `app.setTimeOut({ cExpr: "fn()", nMilliseconds: 500 });`.
  4. Guard explicitly for `null` since the default parameter does not cover it.

Example fix

// before
app.setTimeOut("recalc()", "500");   // string -> TypeError
app.setTimeOut("recalc()", null);     // null bypasses default -> TypeError
// after
app.setTimeOut("recalc()", 500);
app.setTimeOut("recalc()", Number(field.value) || 0);
app.setTimeOut({ cExpr: "recalc()", nMilliseconds: 500 });
Defensive patterns

Strategy: type-guard

Validate before calling

function safeSetTimeOut(cExpr, nMilliseconds) {
  if (typeof nMilliseconds !== "number" || Number.isNaN(nMilliseconds)) {
    nMilliseconds = Number(nMilliseconds) || 0;
  }
  return app.setTimeOut(cExpr, nMilliseconds);
}

Type guard

const isTimeoutDelay = (v) => typeof v === "number" && !Number.isNaN(v);
// usage: isTimeoutDelay(field.value) ? app.setTimeOut(fn, field.value) : app.setTimeOut(fn, 0);

Try / catch

try { app.setTimeOut(cExpr, nMilliseconds); }
catch (e) {
  if (e instanceof TypeError && /setTimeOut must be a number/.test(e.message)) {
    app.setTimeOut(cExpr, Number(nMilliseconds) || 0); // retry with coerced value
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling `app.setTimeOut(cExpr, nMilliseconds)` positionally with a non-number second argument: a string like "500", `null`, `true`, or an object. Note the default `nMilliseconds = 0` only kicks in for `undefined`; passing `null` bypasses the default so `typeof null === "object"` and the guard throws. The labeled-object form rarely throws because `cExpr.nMilliseconds || 0` coerces to a number.

Common situations: A form reads the delay from a field whose `.value` is a string; scripts ported from Acrobat that relied on implicit string-to-number coercion; passing `null` intentionally to mean 'no delay'; or a typo passing the callback function instead of a string (which instead trips the first-argument guard just above).

Understand the failure class

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/ee237ad79db49d7c. Report an issue: GitHub.