linshenkx/prompt-optimizer · error · Error

Failed to decode image data URL payload

Error message

Failed to decode image data URL payload

What it means

After FileReader.readAsDataURL produces a data URL, parseDataUrlPayload extracts the base64 and MIME parts. If parsing yields no b64 component the function throws, meaning the data URL was malformed (empty result, missing comma, unparsable header) and the payload could not be recovered.

Source

Thrown at packages/ui/src/utils/image-asset-storage.ts:122

    return { b64, mimeType: finalMimeType }
  }

  if (typeof FileReader === 'undefined') {
    throw new Error('FileReader is not available to decode image payload')
  }

  const blob = new Blob([ab], { type: finalMimeType })

  const dataUrl = await new Promise<string>((resolve, reject) => {
    const reader = new FileReader()
    reader.onerror = () => reject(new Error('Failed to read image blob'))
    reader.onload = () => resolve(String(reader.result || ''))
    reader.readAsDataURL(blob)
  })

  const parsed = parseDataUrlPayload(dataUrl)
  if (!parsed?.b64) {
    throw new Error('Failed to decode image data URL payload')
  }

  return {
    b64: parsed.b64,
    mimeType: parsed.mimeType || finalMimeType,
  }
}

export const normalizeImageSourceToPayload = async (
  source: string,
): Promise<ImagePayload | null> => {
  const raw = String(source || '').trim()
  if (!raw) return null

  const dataUrlPayload = parseDataUrlPayload(raw)
  if (dataUrlPayload) return dataUrlPayload

  if (/^https?:\/\//u.test(raw)) {

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Inspect the fetched response: log content-type and byte length; a 200 with empty body commonly causes this
  2. Validate bytes.length > 0 before requesting payload conversion
  3. If using a FileReader polyfill, ensure it emits standard 'data:<mime>;base64,<data>' output
  4. Fall back to Buffer/btoa-based encoding when the data URL path fails

Example fix

// before
const payload = await normalizeImageSourceToPayload(url) // empty 200 body -> throws

// after
const resp = await fetch(url)
if (!resp.ok || (await resp.clone().arrayBuffer()).byteLength === 0) {
  throw new Error('Empty image response')
}
const payload = await normalizeImageSourceToPayload(url)
Defensive patterns

Strategy: validation

Validate before calling

const resp = await fetch(url)
const ab = await resp.arrayBuffer()
if (ab.byteLength === 0) throw new Error('Empty image response')
// only then hand off to payload normalization

Type guard

const isWellFormedDataUrl = (s: string): boolean =>
  /^data:[\w./+-]+;base64,[A-Za-z0-9+/]+={0,2}$/.test(s)

Try / catch

try { await fetchImagePayloadFromUrl(url) } catch (e) { if (e.message === 'Failed to decode image data URL payload') { /* check empty body / polyfill, retry with btoa path */ } else throw e }

Prevention

When it happens

Trigger: FileReader resolves with an empty or non-standard result string (e.g. '' from a zero-byte blob), a data URL without the 'data:...;base64,' structure, or readAsDataURL returning a plain-URL result for unusual MIME types; parseDataUrlPayload then returns null/empty and the guard fires.

Common situations: Zero-byte responses from a failing server with 200 status; exotic MIME types where the browser emits a non-standard data URL; reader.result being unexpectedly coerced (String(reader.result || '') masking undefined); custom FileReader polyfills emitting wrong formats.

Understand the failure class

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/3a233217f63b5fc5. Report an issue: GitHub.