linshenkx/prompt-optimizer · warning · Error

Failed to decode image data URL

Error message

Failed to decode image data URL

What it means

After fetching image bytes, the blob is read via FileReader.readAsDataURL and the resulting data URL must match /^data:.*?;base64,(.*)$/u. If no base64 segment is captured (b64 is empty), the decode is considered failed. This is a browser-side encoding anomaly, not an HTTP failure.

Source

Thrown at packages/ui/src/composables/app/useAppPromptGardenImport.ts:766

  }

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

  const blob = await resp.blob()
  const actualMime = blob.type || mimeType
  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 match = dataUrl.match(/^data:.*?;base64,(.*)$/u)
  const b64 = match ? match[1] : ''
  if (!b64) {
    throw new Error('Failed to decode image data URL')
  }
  return { b64, mimeType: actualMime || 'application/octet-stream' }
}

const dedupeStrings = (items: string[]): string[] => {
  return Array.from(new Set(items.filter(Boolean)))
}

const buildAssetSourceMetadata = (snapshot: GardenSnapshot): { prompt?: string } => {
  if (snapshot.prompt.format !== 'text') {
    return {}
  }

  const prompt = typeof snapshot.prompt.text === 'string' ? snapshot.prompt.text.trim() : ''
  if (!prompt) return {}
  return { prompt }
}

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Log the actual dataUrl string to see what readAsDataURL produced; check for 'data:,' or an empty payload
  2. Verify content-type of the image response is a normal image mime (image/png, image/jpeg); fix the server's header if wrong
  3. Check the response body length (content-length) to rule out empty 200 responses
  4. As a fallback, convert via arrayBuffer + btoa instead of FileReader for deterministic base64 encoding

Example fix

// before
reader.readAsDataURL(blob)
const b64 = dataUrl.match(/^data:.*?;base64,(.*)$/u)?.[1] ?? ''

// after
const buf = new Uint8Array(await blob.arrayBuffer())
let bin = ''
buf.forEach(b => bin += String.fromCharCode(b))
const b64 = btoa(bin)
Defensive patterns

Strategy: fallback

Validate before calling

if (blob.size === 0) throw new Error('Empty image blob')
if (!/^image\//.test(blob.type)) console.warn('Unexpected image mime:', blob.type)

Type guard

const isBase64DataUrl = (u: string): boolean => /^data:.*?;base64,.+/u.test(u)

Try / catch

try { return decodeViaFileReader(blob) } catch { return decodeViaArrayBuffer(blob) /* btoa fallback */ }

Prevention

When it happens

Trigger: readAsDataURL produced a data URL without a base64 payload — e.g. an empty or tiny blob, a non-standard mime yielding 'data:,', or browser/encoding edge cases (unusual content-types, blob closed prematurely) that yield a data URL not matching the regex.

Common situations: Zero-byte response bodies with 200 status; content-type headers that make the browser emit a plain (non-base64) data URL; unusual mime types from object storage; race where the blob handle was revoked before reading.

Understand the failure class

Related errors


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