mozilla/pdf.js · error · Error

doc.title is read-only

Error message

doc.title is read-only

What it means

`Doc.title` returns the document's Title metadata string (`this._title`), set at parse time from the info dictionary / XMP. It is read-only per the Acrobat spec because PDF.js scripting does not persist metadata changes back to the file. The throwing setter enforces that contract so a script cannot silently alter the stored title.

Source

Thrown at src/scripting_api/doc.js:679

  set subject(_) {
    throw new Error("doc.subject is read-only");
  }

  get templates() {
    return [];
  }

  set templates(_) {
    throw new Error("doc.templates is read-only");
  }

  get title() {
    return this._title;
  }

  set title(_) {
    throw new Error("doc.title is read-only");
  }

  get URL() {
    return this._URL;
  }

  set URL(_) {
    throw new Error("doc.URL is read-only");
  }

  get viewState() {
    return undefined;
  }

  set viewState(_) {
    throw new Error("doc.viewState is read-only");
  }

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Remove the assignment; read the value (`var t = doc.title;`).
  2. Set the title at PDF authoring/generation time so it is embedded in the file.
  3. Guard legacy scripts with try/catch to tolerate the write attempt.

Example fix

// before
doc.title = 'Invoice 2026';

// after
var t = doc.title; // read-only metadata
Defensive patterns

Strategy: validation

Validate before calling

const READ_ONLY_DOC_PROPS = new Set(['title','subject','author','creator','keywords','producer' /* ... */]);
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, 'title'); // true

Try / catch

try {
  doc.title = 'My Title';
} catch (e) {
  if (/title is read-only/.test(e.message)) console.warn(e.message);
  else throw e;
}

Prevention

When it happens

Trigger: A script writes `doc.title = 'My Title';`, typically as branding or on save. The setter throws on assignment.

Common situations: Metadata-edit scripts from desktop Acrobat; branding workflows; code assuming in-script title setters are persisted.

Related errors


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