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
- Pass a numeric literal or coerce first: `app.setTimeOut("fn()", Number(value))`.
- If the value comes from a field, coerce at the source: `const ms = Number(this.getField("delay").value) || 0;`.
- Use the labeled-object form which safely defaults a missing delay: `app.setTimeOut({ cExpr: "fn()", nMilliseconds: 500 });`.
- 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
- Always coerce field-derived delay values with `Number(x) || 0` before passing them to `setTimeOut`/`setInterval`.
- Remember the `nMilliseconds = 0` default only applies to `undefined`, not `null`.
- Prefer the labeled-object form when juggling optional arguments.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- First argument of app.setTimeOut must be a string
- doc.info.${prop} is read-only
- doc.author is read-only
- doc.bookmarkRoot is read-only
- doc.creator is read-only
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/ee237ad79db49d7c.
Report an issue: GitHub.