{"record":{"id":"46b3aadf26c182e4","repo":"mozilla/pdf.js","slug":"doc-numpages-is-read-only","errorCode":null,"errorMessage":"doc.numPages is read-only","messagePattern":"doc\\.numPages is read-only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scripting_api/doc.js","lineNumber":534,"sourceCode":"\n  set nocache(nocache) {\n    this._nocache = nocache;\n  }\n\n  get numFields() {\n    return this._numFields;\n  }\n\n  set numFields(_) {\n    throw new Error(\"doc.numFields is read-only\");\n  }\n\n  get numPages() {\n    return this._numPages;\n  }\n\n  set numPages(_) {\n    throw new Error(\"doc.numPages is read-only\");\n  }\n\n  get numTemplates() {\n    return 0;\n  }\n\n  set numTemplates(_) {\n    throw new Error(\"doc.numTemplates is read-only\");\n  }\n\n  get outerAppWindowRect() {\n    return [0, 0, 0, 0];\n  }\n\n  set outerAppWindowRect(_) {\n    throw new Error(\"doc.outerAppWindowRect is read-only\");\n  }\n","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/scripting_api/doc.js#L516-L552","documentation":"`Doc.numPages` returns the number of pages in the document (`this._numPages`), set when the document is loaded. It is read-only by the Acrobat spec — page count changes only through page insertion/deletion APIs, never by assignment. PDF.js installs a throwing setter so a script that tries `doc.numPages = n` fails loudly and consistently with Acrobat.","triggerScenarios":"A script assigns to `doc.numPages` (e.g. `doc.numPages = 5;`), typically from a mistaken belief that it resizes the document. The setter throws on that line.","commonSituations":"Scripts ported from engines where page count is settable; form-init code trying to fix a page count; copy-pasted snippet from a non-PDFjs tutorial.","solutions":["Read the value (`var n = doc.numPages;`) instead of writing it.","Use the appropriate page add/delete APIs exposed by your integration if page mutation is required (PDF.js does not expose `newPage`/`deletePages` in the scripting sandbox).","Wrap script execution in try/catch so a stray assignment is logged and ignored."],"exampleFix":"// before\ndoc.numPages = 10;\n\n// after\nvar pages = doc.numPages; // read-only, reflects actual page count","handlingStrategy":"validation","validationCode":"const READ_ONLY_DOC_PROPS = new Set(['numPages','numFields' /* ... */]);\nfunction assertsNoReadOnlyWrite(scriptSrc) {\n  for (const p of READ_ONLY_DOC_PROPS) {\n    if (new RegExp(`\\\\bdoc\\\\.${p}\\\\s*=[^=]`).test(scriptSrc)) {\n      throw new Error(`Script writes read-only property doc.${p}`);\n    }\n  }\n}\nassertsNoReadOnlyWrite(myScript);","typeGuard":"function isReadOnlyDocProp(doc, prop) {\n  const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(doc), prop)\n    || Object.getOwnPropertyDescriptor(doc, prop);\n  return !!desc && !!desc.get && !desc.set;\n}\nisReadOnlyDocProp(doc, 'numPages'); // true","tryCatchPattern":"try {\n  doc.numPages = 10;\n} catch (e) {\n  if (/numPages is read-only/.test(e.message)) console.warn(e.message);\n  else throw e;\n}","preventionTips":["Page count is read-only; mutate pages via dedicated APIs, never by assignment.","Static-lint scripts for `doc.numPages =` before dispatching to the sandbox.","Run untrusted scripts under try/catch so a stray assignment does not abort the form."],"tags":["scripting","acrobat-js-api","doc-object","read-only","pages"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}