mozilla/pdf.js · error · Error

doc.mouseX is read-only

Error message

doc.mouseX is read-only

What it means

PDF.js implements the Acrobat JavaScript `Doc` object inside its scripting sandbox. `Doc.mouseX` is a read-only getter returning the cursor's X coordinate (in points) relative to the page's top-left corner; PDF.js always returns 0 because it does not feed live cursor position into the scripting context. The setter throws `doc.mouseX is read-only` because the Acrobat JavaScript Scripting Reference marks mouseX as a read-only property, so PDF.js installs a throwing setter to mirror the spec rather than silently accepting writes.

Source

Thrown at src/scripting_api/doc.js:494

  set metadata(metadata) {
    this._metadata = metadata;
  }

  get modDate() {
    return this._modDate;
  }

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

  get mouseX() {
    return 0;
  }

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

  get mouseY() {
    return 0;
  }

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

  get noautocomplete() {
    return this._noautocomplete;
  }

  set noautocomplete(noautocomplete) {
    this._noautocomplete = noautocomplete;
  }

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Remove the assignment to `doc.mouseX` — read it instead (`var x = doc.mouseX;`).
  2. If you need the event mouse coordinate, read the `event` object (`event.x`, `event.targetX`, `event.rc`) in the action handler where the click occurred.
  3. Wrap third-party/legacy script execution in a try/catch at the host integration layer so a read-only write logs and continues instead of killing the whole form script.

Example fix

// before
doc.mouseX = 100;

// after
var x = doc.mouseX; // read-only; returns 0 in PDF.js
Defensive patterns

Strategy: try-catch

Validate before calling

// Read-only by spec; validate intent before running a script that may write it.
const READ_ONLY_DOC_PROPS = new Set(['mouseX','mouseY' /* ...other read-only Doc props */]);
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

// PDF.js Doc getters are writable===false; detect at runtime in the sandbox.
function isReadOnlyDocProp(doc, prop) {
  const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(doc), prop)
    || Object.getOwnPropertyDescriptor(doc, prop);
  return !!desc && desc.get && !desc.set;
}
isReadOnlyDocProp(doc, 'mouseX'); // true

Try / catch

try {
  doc.mouseX = 100; // legacy/3rd-party script line
} catch (e) {
  if (/mouseX is read-only/.test(e.message)) {
    console.warn('Ignored read-only write:', e.message);
  } else { throw e; }
}

Prevention

When it happens

Trigger: A PDF form/document script executes an assignment to `this.mouseX` or `doc.mouseX` (e.g. `doc.mouseX = event.x;` inside a MouseUp/Calculate action). The throwing setter is invoked immediately and aborts the running script action.

Common situations: Porting an AcroJS/XFA script written for desktop Acrobat that tried to reposition or echo the cursor; copy-pasted sample code from an Acrobat SDK tutorial; an obfuscated or generated script that blindly assigns to every `Doc` property.

Related errors


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