{"record":{"id":"af10e673dcebe224","repo":"mozilla/pdf.js","slug":"app-numplugins-is-read-only","errorCode":null,"errorMessage":"app.numPlugins is read-only","messagePattern":"app\\.numPlugins is read-only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scripting_api/app.js","lineNumber":281,"sourceCode":"\n  set media(_) {\n    throw new Error(\"app.media is read-only\");\n  }\n\n  get monitors() {\n    return [];\n  }\n\n  set monitors(_) {\n    throw new Error(\"app.monitors is read-only\");\n  }\n\n  get numPlugins() {\n    return 0;\n  }\n\n  set numPlugins(_) {\n    throw new Error(\"app.numPlugins is read-only\");\n  }\n\n  get openInPlace() {\n    return this._openInPlace;\n  }\n\n  set openInPlace(val) {\n    this._openInPlace = val;\n    /* TODO */\n  }\n\n  get platform() {\n    return this._platform;\n  }\n\n  set platform(_) {\n    throw new Error(\"app.platform is read-only\");\n  }","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/scripting_api/app.js#L263-L299","documentation":"app.numPlugins returns 0 because PDF.js loads no Acrobat-style plugins. It is a viewer-managed count and is not assignable; the setter throws. The throw prevents spoofing the plugin count.","triggerScenarios":"PDF JavaScript or caller runs app.numPlugins = N; the setter at src/scripting_api/app.js:281 throws regardless of value.","commonSituations":"Scripts trying to fake plugin availability to gate features; authors confusing the stub with a registry length.","solutions":["Read app.numPlugins (always 0 in PDF.js) for capability detection.","Gate plugin-dependent features on app.numPlugins > 0, expecting false.","Do not attempt to change the value from document scripts."],"exampleFix":"// before\napp.numPlugins = 3;\n// after\nif (app.numPlugins > 0) { /* ... */ } else { /* unsupported */ }","handlingStrategy":"validation","validationCode":"// app.numPlugins is always 0 in pdf.js.\nconst pluginsAvailable = (app) => app.numPlugins > 0;","typeGuard":"const isNonNegativeInt = (v) => Number.isInteger(v) && v >= 0;","tryCatchPattern":"try { /* code that may assign app.numPlugins */ }\ncatch (e) { if (!/numPlugins is read-only/.test(e.message)) throw e; }","preventionTips":["Gate plugin features on numPlugins/plugins length.","Expect 0 and an empty array in pdf.js.","Never try to fake plugin counts from document JS."],"tags":["scripting-api","read-only","stub","acrobat-js"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}