mozilla/pdf.js · error · Error
doc.numFields is read-only
Error message
doc.numFields is read-only
What it means
`Doc.numFields` returns the count of interactive fields in the document, backed by `this._numFields` (derived from the field map built when the document is parsed). Acrobat defines it as read-only because field count only changes through `addField`/`removeField`, not by direct assignment. PDF.js's throwing setter enforces that contract so scripts get an immediate, spec-consistent failure instead of a silently-ignored write.
Source
Thrown at src/scripting_api/doc.js:526
set noautocomplete(noautocomplete) {
this._noautocomplete = noautocomplete;
}
get nocache() {
return this._nocache;
}
set nocache(nocache) {
this._nocache = nocache;
}
get numFields() {
return this._numFields;
}
set numFields(_) {
throw new Error("doc.numFields is read-only");
}
get numPages() {
return this._numPages;
}
set numPages(_) {
throw new Error("doc.numPages is read-only");
}
get numTemplates() {
return 0;
}
set numTemplates(_) {
throw new Error("doc.numTemplates is read-only");
}
View on GitHub (pinned to 5903d58d58)
Solutions
- Use `addField(...)` / `removeField(...)` to change the count, then read `doc.numFields` to observe it.
- Replace any `doc.numFields = ...` with a local variable that tracks your own counter.
- Gate legacy scripts with a try/catch at the host so the error is non-fatal.
Example fix
// before
doc.numFields = doc.numFields + 1;
// after
doc.addField('NewField', 'text', [0], 0);
console.log(doc.numFields); // now reflects the new count Defensive patterns
Strategy: validation
Validate before calling
const READ_ONLY_DOC_PROPS = new Set(['numFields','numPages' /* ... */]);
function assertsNoReadOnlyWrite(scriptSrc) {
for (const p of READ_ONLY_DOC_PROPS) {
if (new RegExp(`\\bdoc\\.${p}\\s*=[^=]`).test(scriptSrc)) {
throw new Error(`Script writes read-only property doc.${p}`);
}
}
}
assertsNoReadOnlyWrite(myScript); Type guard
function isReadOnlyDocProp(doc, prop) {
const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(doc), prop)
|| Object.getOwnPropertyDescriptor(doc, prop);
return !!desc && !!desc.get && !desc.set;
}
isReadOnlyDocProp(doc, 'numFields'); // true Try / catch
try {
doc.numFields = n;
} catch (e) {
if (/numFields is read-only/.test(e.message)) console.warn(e.message);
else throw e;
} Prevention
- Change field count only through `addField`/`removeField`; read `doc.numFields` to observe it.
- Lint scripts for assignments to read-only count properties before execution.
- Wrap legacy scripts in try/catch at the host dispatch boundary.
When it happens
Trigger: A script writes `doc.numFields = n;` or `doc.numFields++`, often as a misguided attempt to pre-size or reset the field collection. The throwing setter aborts the action.
Common situations: A script incorrectly assumes `numFields` is a mutable capacity/length; code ported from a different form engine where field count is settable; debugging code that assigns to counters.
Related errors
- doc.mouseX is read-only
- doc.mouseY is read-only
- doc.numPages is read-only
- doc.numTemplates is read-only
- doc.outerAppWindowRect is read-only
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/60dfbebe7f8fca04.
Report an issue: GitHub.