{"record":{"id":"bea10444f4638101","repo":"linshenkx/prompt-optimizer","slug":"filereader-is-not-available-to-decode-image-payloa","errorCode":null,"errorMessage":"FileReader is not available to decode image payload","messagePattern":"FileReader is not available to decode image payload","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/image-asset-storage.ts","lineNumber":108,"sourceCode":"  const bytes = new Uint8Array(ab)\n  const inferredMimeType = inferMimeTypeFromBytes(bytes)\n  const finalMimeType =\n    mimeType && mimeType !== 'application/octet-stream'\n      ? mimeType\n      : inferredMimeType || mimeType || 'application/octet-stream'\n\n  type BufferLike = {\n    from: (data: ArrayBuffer) => { toString: (encoding: 'base64') => string }\n  }\n\n  const maybeBuffer = (globalThis as unknown as { Buffer?: BufferLike }).Buffer\n  if (maybeBuffer && typeof maybeBuffer.from === 'function') {\n    const b64 = maybeBuffer.from(ab).toString('base64')\n    return { b64, mimeType: finalMimeType }\n  }\n\n  if (typeof FileReader === 'undefined') {\n    throw new Error('FileReader is not available to decode image payload')\n  }\n\n  const blob = new Blob([ab], { type: finalMimeType })\n\n  const dataUrl = await new Promise<string>((resolve, reject) => {\n    const reader = new FileReader()\n    reader.onerror = () => reject(new Error('Failed to read image blob'))\n    reader.onload = () => resolve(String(reader.result || ''))\n    reader.readAsDataURL(blob)\n  })\n\n  const parsed = parseDataUrlPayload(dataUrl)\n  if (!parsed?.b64) {\n    throw new Error('Failed to decode image data URL payload')\n  }\n\n  return {\n    b64: parsed.b64,","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/image-asset-storage.ts#L90-L126","documentation":"After fetching image bytes, the code needs to base64-encode the ArrayBuffer. It tries Node's Buffer first; if Buffer is unavailable (browser), it falls back to FileReader.readAsDataURL. This error is thrown when neither exists — an environment with no Buffer and no FileReader (e.g. some Edge/worker runtimes, jsdom misconfig, or older Node without DOM globals).","triggerScenarios":"Running normalizeImageSourceToPayload / fetchImagePayloadFromUrl in a Web Worker or SSR runtime where global Buffer is absent or Buffer.from is not a function and globalThis.FileReader is undefined; test environments (jest/jsdom) that don't polyfill FileReader.","commonSituations":"Server-side rendering in Node with Buffer tree-shaken away or shadowed; Vitest/Jest with a minimal environment; Web Workers in Safari or older runtimes lacking FileReader; exotic runtimes like certain edge functions.","solutions":["Polyfill FileReader in the environment (e.g. set globalThis.FileReader from a polyfill package in test setup)","Ensure Node's Buffer global is available and untouched (don't set Buffer: undefined in tsconfig/vite config)","Preload a polyfill such as 'blob-polyfill' in workers/tests","Avoid this code path in workers: convert via btoa/atob or fetch as blob and use Response.arrayBuffer alternatives"],"exampleFix":"// before\n// vitest test hitting fetchImagePayloadFromUrl\nconst payload = await normalizeImageSourceToPayload(url) // throws in node env without FileReader\n\n// after\n// vitest.setup.ts\nimport { FileReader } from 'blob-polyfill'\nif (typeof globalThis.FileReader === 'undefined') globalThis.FileReader = FileReader\nconst payload = await normalizeImageSourceToPayload(url)","handlingStrategy":"fallback","validationCode":"if (typeof FileReader === 'undefined' && typeof Buffer === 'undefined') {\n  await installFileReaderPolyfill() // e.g. blob-polyfill\n}","typeGuard":"const canEncodePayload = (): boolean =>\n  (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') ||\n  typeof FileReader !== 'undefined'","tryCatchPattern":"try { await normalizeImageSourceToPayload(url) } catch (e) { if (e.message.includes('FileReader is not available')) { await polyfillFileReader(); return retry() } throw e }","preventionTips":["Add FileReader/Buffer polyfills in test setup files","Don't strip Node's Buffer global in build configs","Guard worker code paths with feature detection before fetching"],"tags":["environment","polyfill","filereader","base64","runtime"],"backgroundTag":"missing-web-api-polyfill","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}