{"record":{"id":"50cca6a498136290","repo":"mozilla/pdf.js","slug":"thermometer-cancelled-is-read-only","errorCode":null,"errorMessage":"thermometer.cancelled is read-only","messagePattern":"thermometer\\.cancelled is read-only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scripting_api/thermometer.js","lineNumber":32,"sourceCode":" */\n\nimport { PDFObject } from \"./pdf_object.js\";\n\nclass Thermometer extends PDFObject {\n  _cancelled = false;\n\n  _duration = 100;\n\n  _text = \"\";\n\n  _value = 0;\n\n  get cancelled() {\n    return this._cancelled;\n  }\n\n  set cancelled(_) {\n    throw new Error(\"thermometer.cancelled is read-only\");\n  }\n\n  get duration() {\n    return this._duration;\n  }\n\n  set duration(val) {\n    this._duration = val;\n  }\n\n  get text() {\n    return this._text;\n  }\n\n  set text(val) {\n    this._text = val;\n  }\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/scripting_api/thermometer.js#L14-L50","documentation":"Thrown by the setter of `Thermometer.cancelled` (src/scripting_api/thermometer.js:32). A `Thermometer` (progress bar) object exposes `cancelled` so scripts can detect user cancellation; PDF.js treats it as read-only state driven by the host, so programmatic assignment throws. The other thermomemeter properties (`duration`, `text`, `value`) are writable.","triggerScenarios":"A long-running script does `thermo.cancelled = true;` to try to abort itself, or generic state-restore code that writes every read property back.","commonSituations":"Scripts that conflate 'request cancellation' with 'set the flag'; polling-progress routines that mirror the thermometer object into another structure and back.","solutions":["Read `cancelled` only, and break out of your loop when it becomes true instead of assigning it.","To stop the thermometer, call `thermo.end()` rather than setting `cancelled`.","Wrap the assignment in try/catch if it originates in unchangeable generic code."],"exampleFix":"// before\nthermo.cancelled = true;\n// after\n// signal cancellation through your own flag and end the thermometer:\nthermo.end();","handlingStrategy":"try-catch","validationCode":"const READ_ONLY_THERMO_PROPS = new Set(['cancelled']);\nfunction isWritableThermoProp(key) {\n  return !READ_ONLY_THERMO_PROPS.has(key);\n}","typeGuard":null,"tryCatchPattern":"try {\n  thermo.cancelled = true;\n} catch (e) {\n  // cancelled is read-only; end the thermometer instead\n  thermo.end();\n}","preventionTips":["Read thermo.cancelled in your loop and break when true; do not write it.","Call thermo.end() to stop the progress indicator.","Do not mirror the thermometer object through serialization that writes every property back."],"tags":["scripting-api","thermometer","read-only","acrobat-js"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}