{"record":{"id":"d7ea3ae69f895969","repo":"fabricjs/fabric.js","slug":"loadimage","errorCode":null,"errorMessage":"loadImage","messagePattern":"loadImage","errorType":"exception","errorClass":"SignalAbortedError","httpStatus":null,"severity":"warning","filePath":"packages/core/src/util/misc/objectEnlive.ts","lineNumber":44,"sourceCode":" * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n  url: string,\n  { signal, crossOrigin = null, resourceValidator }: LoadImageOptions = {},\n): Promise<HTMLImageElement> => {\n  if (signal && signal.aborted) {\n    return Promise.reject(new SignalAbortedError('loadImage'));\n  }\n  if (url && resourceValidator) {\n    return Promise.resolve()\n      .then(() => resourceValidator(url))\n      .then((isAllowed) => {\n        if (!isAllowed) {\n          throw new FabricError(`Resource '${url}' is not allowed`);\n        }\n        if (signal && signal.aborted) {\n          throw new SignalAbortedError('loadImage');\n        }\n        return loadImage(url, { signal, crossOrigin });\n      });\n  }\n  return new Promise<HTMLImageElement>(function (resolve, reject) {\n    if (signal && signal.aborted) {\n      return reject(new SignalAbortedError('loadImage'));\n    }\n    const img = createImage();\n    let abort: EventListenerOrEventListenerObject;\n    if (signal) {\n      abort = function (err: Event) {\n        img.src = '';\n        reject(err);\n      };\n      signal.addEventListener('abort', abort, { once: true });\n    }\n    const done = function () {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/fabricjs/fabric.js/blob/2bd4992cabf4ec9609aa349ea09b723cadc94bef/packages/core/src/util/misc/objectEnlive.ts#L26-L62","documentation":"SignalAbortedError thrown by loadImage when the options.signal is already aborted before the image load starts (or after the resourceValidator async check completes). It is the standard AbortSignal integration: aborting an enliven/load operation should cancel pending image fetches, and fabric surfaces that as a distinct error type rather than a generic failure.","triggerScenarios":"Calling fabric.loadImage(url, { signal }) with an already-aborted AbortController's signal, or the controller being aborted while the resourceValidator promise resolves. Also occurs during canvas.loadFromJSON when the caller aborts mid-enliven.","commonSituations":"React components that abort a controller on unmount and then a late-loading image starts with the dead signal; race conditions where cleanup runs before load; passing a shared controller's signal that another operation already aborted.","solutions":["Check signal.aborted before starting the load and skip it if aborted","Ensure the AbortController isn't aborted prematurely (e.g. abort on unmount only when the load is truly obsolete)","Catch SignalAbortedError specifically and treat it as a cancel, not a failure (skip UI error states)","Create a fresh controller per load instead of reusing an aborted one"],"exampleFix":"// before\nconst img = await fabric.loadImage(url, { signal: controller.signal }); // throws SignalAbortedError('loadImage')\n\n// after\nif (!controller.signal.aborted) {\n  const img = await fabric.loadImage(url, { signal: controller.signal });\n}","handlingStrategy":"try-catch","validationCode":"if (!controller.signal.aborted) {\n  img = await fabric.loadImage(url, { signal: controller.signal });\n}","typeGuard":"const isAborted = (signal?: AbortSignal): boolean => !!signal?.aborted;","tryCatchPattern":"try {\n  await fabric.loadImage(url, { signal: controller.signal });\n} catch (e) {\n  if (e.name === 'SignalAbortedError' || controller.signal.aborted) {\n    // cancelled: silently return, do not surface as an error\n  } else throw e;\n}","preventionTips":["Check signal.aborted before kicking off loads","Use a fresh AbortController per load","Abort only when the result is truly obsolete","Handle SignalAbortedError as cancellation, not failure"],"tags":["abort","signal","async","image","cancellation"],"backgroundTag":"abort-signal-aborted","analyzedSha":"2bd4992cabf4ec9609aa349ea09b723cadc94bef","analyzedAt":"2026-08-28T10:56:44.286Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}