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
- Remove the assignment to `doc.mouseX` — read it instead (`var x = doc.mouseX;`).
- 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.
- 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
- Treat all Acrobat-JS `Doc` geometry/mouse properties as read-only unless the Acrobat Scripting Reference explicitly lists a setter.
- Lint scripts against a known set of read-only Doc properties before dispatching them to the sandbox.
- Wrap third-party or legacy form-script execution in a try/catch boundary so one read-only write does not abort the whole form.
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
- doc.mouseY is read-only
- doc.numFields 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/e74d1b153afee905.
Report an issue: GitHub.