{"record":{"id":"b654a80ab473b866","repo":"mozilla/pdf.js","slug":"error-from-the-ai-service","errorCode":null,"errorMessage":"Error from the AI service.","messagePattern":"Error from the AI service\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/display/editor/stamp.js","lineNumber":186,"sourceCode":"      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.\");\n    }\n    if (response.cancel) {\n      return null;\n    }\n    if (!response.output) {\n      throw new Error(\"No valid response from the AI service.\");\n    }\n    const altText = response.output;\n    await this.setGuessedAltText(altText);\n    if (updateAltTextData && !this.hasAltTextData()) {\n      this.altTextData = { alt: altText, decorative: false };\n    }\n    return altText;\n  }\n\n  #getBitmap() {\n    if (this.#bitmapId) {\n      this._uiManager.enableWaiting(true);","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/display/editor/stamp.js#L168-L204","documentation":"Thrown by StampEditor.mlGuessAltText when the 'altText' guess response carries a truthy `error` field. Unlike the no-response case, the ML service did reply, but the payload signals a backend-side failure (model error, bad input, rate limit, etc.). The library surfaces this as a distinct, non-recoverable error for that guess attempt.","triggerScenarios":"mlManager.guess({ name:'altText', request:{data,width,height,channels} }) resolves to an object whose `error` property is truthy (e.g. { error: 'model timeout' }).","commonSituations":"The image data payload is malformed or too large; the deployed alt-text model rejects the input; the backend is rate-limiting or temporarily failing; channels (data.length/(width*height)) computes to an unexpected value due to a zero-size canvas.","solutions":["Inspect response.error from your mlManager to identify the backend-reported cause.","Verify the imageData passed in has consistent width, height, and channels (data.length === width*height*channels).","Retry the guess after a short delay if the backend error is transient.","Catch the error and fall back to the manual alt-text dialog so the editor stays usable."],"exampleFix":"// before\nconst alt = await editor.mlGuessAltText();\n// after\ntry {\n  const alt = await editor.mlGuessAltText();\n} catch (e) {\n  if (e.message === 'Error from the AI service.') {\n    // log backend cause and fall back\n  }\n}","handlingStrategy":"try-catch","validationCode":"if (imageData.width <= 0 || imageData.height <= 0 || imageData.data.length === 0) {\n  // do not call mlGuessAltText with bad image data\n}","typeGuard":"function isValidImageDataForGuess({ data, width, height }) {\n  return width > 0 && height > 0 && data.length === width * height * (data.length / (width * height));\n}","tryCatchPattern":"try {\n  const alt = await editor.mlGuessAltText();\n} catch (e) {\n  if (e.message.startsWith('Error from the AI service.')) {\n    // log and fall back to manual entry\n  }\n}","preventionTips":["Validate image data dimensions/length are consistent before guessing.","Inspect mlManager.guess response.error to find the backend cause.","Retry transient backend errors with backoff before giving up.","Keep the manual alt-text dialog as the persistent fallback."],"tags":["ai","alt-text","ml-manager","backend-error"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}