{"record":{"id":"ef502c314dacc907","repo":"mozilla/pdf.js","slug":"ml-isn-t-enabled-for-alt-text","errorCode":null,"errorMessage":"ML isn't enabled for alt text.","messagePattern":"ML isn't enabled for alt text\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/display/editor/stamp.js","lineNumber":168,"sourceCode":"        // text.\n        this.mlGuessAltText();\n      } catch {}\n    }\n\n    this.div.focus();\n  }\n\n  async mlGuessAltText(imageData = null, updateAltTextData = true) {\n    if (this.hasAltTextData()) {\n      return null;\n    }\n\n    const { mlManager } = this._uiManager;\n    if (!mlManager) {\n      throw new Error(\"No ML.\");\n    }\n    if (!(await mlManager.isEnabledFor(\"altText\"))) {\n      throw new Error(\"ML isn't enabled for alt text.\");\n    }\n    const { data, width, height } =\n      imageData ||\n      this.copyCanvas(null, null, /* createImageData = */ true).imageData;\n    const response = await mlManager.guess({\n      name: \"altText\",\n      request: {\n        data,\n        width,\n        height,\n        channels: data.length / (width * height),\n      },\n    });\n    if (!response) {\n      throw new Error(\"No response from the AI service.\");\n    }\n    if (response.error) {\n      throw new Error(\"Error from the AI service.\");","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/display/editor/stamp.js#L150-L186","documentation":"Thrown by StampEditor.mlGuessAltText when an mlManager is registered but await mlManager.isEnabledFor('altText') returns false. The host owns the decision (user opt-out, model not downloaded, policy disabled); PDF.js treats the disabled state as a hard stop rather than attempting the request.","triggerScenarios":"User disabled alt-text ML in host settings; the model has not finished downloading; enterprise policy disabled the feature; calling mlGuessAltText before the user has granted the capability.","commonSituations":"Firefox with the alt-text model toggle off; embedded deployments where isEnabledFor returns false by default; race with model initialization where enabled state flips later.","solutions":["Gate the call on isEnabledFor first and hide/disable the alt-text UI accordingly.","Surface a user-facing setting to enable the alt-text model and re-check after toggling.","Fall back to manual alt-text entry when ML is disabled."],"exampleFix":"// before\nconst alt = await stampEditor.mlGuessAltText(imageData);\n\n// after\nconst ml = stampEditor._uiManager.mlManager;\nif (!ml || !(await ml.isEnabledFor('altText'))) {\n  // show manual alt-text entry instead\n  return null;\n}\nconst alt = await stampEditor.mlGuessAltText(imageData);","handlingStrategy":"validation","validationCode":"async function canGuessAltText(editor) {\n  const ml = editor._uiManager?.mlManager;\n  return !!ml && await ml.isEnabledFor('altText');\n}\nif (await canGuessAltText(stampEditor)) {\n  return stampEditor.mlGuessAltText(imageData);\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Check isEnabledFor('altText') before showing the Guess button.","Re-check on user toggle since the enabled state can change at runtime.","Always provide a manual fallback for alt text."],"tags":["editor","ml","alt-text","feature-flag"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}