{"record":{"id":"918511aa54e84892","repo":"mozilla/pdf.js","slug":"doc-subject-is-read-only","errorCode":null,"errorMessage":"doc.subject is read-only","messagePattern":"doc\\.subject is read-only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scripting_api/doc.js","lineNumber":663,"sourceCode":"\n  set spellDictionaryOrder(spellDictionaryOrder) {\n    this._spellDictionaryOrder = spellDictionaryOrder;\n  }\n\n  get spellLanguageOrder() {\n    return this._spellLanguageOrder;\n  }\n\n  set spellLanguageOrder(spellLanguageOrder) {\n    this._spellLanguageOrder = spellLanguageOrder;\n  }\n\n  get subject() {\n    return this._subject;\n  }\n\n  set subject(_) {\n    throw new Error(\"doc.subject is read-only\");\n  }\n\n  get templates() {\n    return [];\n  }\n\n  set templates(_) {\n    throw new Error(\"doc.templates is read-only\");\n  }\n\n  get title() {\n    return this._title;\n  }\n\n  set title(_) {\n    throw new Error(\"doc.title is read-only\");\n  }\n","sourceCodeStart":645,"sourceCodeEnd":681,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/scripting_api/doc.js#L645-L681","documentation":"`Doc.subject` returns the document's Subject metadata string (`this._subject`), populated at parse time from the document info dictionary / XMP. It is read-only per the Acrobat spec — PDF.js scripting does not persist metadata changes back to the file. The throwing setter enforces that contract so a script cannot silently misrepresent stored metadata.","triggerScenarios":"A script writes `doc.subject = 'New Subject';`, typically in a save/branding workflow. The setter throws on assignment.","commonSituations":"Metadata-edit scripts from desktop Acrobat; branding templates; code that assumes in-script metadata setters persist to disk.","solutions":["Remove the assignment; read the value (`var s = doc.subject;`).","Edit metadata at PDF generation/processing time (it is set by the authoring tool and embedded in the file).","Wrap legacy scripts in try/catch to tolerate the write attempt."],"exampleFix":"// before\ndoc.subject = 'Annual Report';\n\n// after\nvar s = doc.subject; // read-only metadata","handlingStrategy":"validation","validationCode":"const READ_ONLY_DOC_PROPS = new Set(['subject','title','author','creator','keywords','producer' /* ... */]);\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, 'subject'); // true","tryCatchPattern":"try {\n  doc.subject = 'New Subject';\n} catch (e) {\n  if (/subject is read-only/.test(e.message)) console.warn(e.message);\n  else throw e;\n}","preventionTips":["Metadata is read-only in PDF.js scripting; set it at PDF authoring/generation time.","Keep a list of read-only metadata properties and lint scripts against it.","Wrap branding/metadata scripts in try/catch for legacy tolerance."],"tags":["scripting","acrobat-js-api","doc-object","read-only","metadata"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}