linshenkx/prompt-optimizer · error · Error
Image request failed: ${resp.status}
Error message
Image request failed: ${resp.status} What it means
fetchImagePayloadFromUrl performs a GET on an absolute URL and throws when the response status is not ok (outside 2xx). The message includes the HTTP status code, e.g. 'Image request failed: 404'. It is a hard failure from normalizeImageSourceToPayload's remote-fetch path.
Source
Thrown at packages/ui/src/utils/image-asset-storage.ts:84
if (
bytes.length >= 6 &&
bytes[0] === 0x47 &&
bytes[1] === 0x49 &&
bytes[2] === 0x46 &&
bytes[3] === 0x38 &&
(bytes[4] === 0x37 || bytes[4] === 0x39) &&
bytes[5] === 0x61
) {
return 'image/gif'
}
return null
}
const fetchImagePayloadFromUrl = async (absoluteUrl: string): Promise<ImagePayload> => {
const resp = await fetch(absoluteUrl, { method: 'GET' })
if (!resp.ok) {
throw new Error(`Image request failed: ${resp.status}`)
}
const headerType = resp.headers.get('content-type')
const mimeType = typeof headerType === 'string' ? headerType.split(';')[0].trim() : ''
const ab = await resp.arrayBuffer()
const bytes = new Uint8Array(ab)
const inferredMimeType = inferMimeTypeFromBytes(bytes)
const finalMimeType =
mimeType && mimeType !== 'application/octet-stream'
? mimeType
: inferredMimeType || mimeType || 'application/octet-stream'
type BufferLike = {
from: (data: ArrayBuffer) => { toString: (encoding: 'base64') => string }
}
const maybeBuffer = (globalThis as unknown as { Buffer?: BufferLike }).Buffer
if (maybeBuffer && typeof maybeBuffer.from === 'function') {View on GitHub (pinned to 3e677b1d9f)
Solutions
- Check the status in the message: 404 means the URL is wrong/deleted, 403 means auth/hotlink protection, 5xx means retry later
- If using signed URLs, generate a fresh signed URL before fetching
- For transient 5xx, retry with backoff or fall back to a placeholder
- Verify the URL opens in a browser/incognito and that CORS headers allow your origin
Example fix
// before
const payload = await normalizeImageSourceToPayload(url)
// after
let payload
try {
payload = await normalizeImageSourceToPayload(url)
} catch (e) {
if (e instanceof Error && e.message.startsWith('Image request failed:')) {
payload = PLACEHOLDER_PAYLOAD // or re-sign URL and retry
} else throw e
} Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch(url, { method: 'HEAD' })
if (!probe.ok) {
if (probe.status === 403 || probe.status === 401) await refreshSignedUrl()
else throw new Error(`Image unavailable (${probe.status})`)
} Type guard
null
Try / catch
let lastErr
for (const delay of [0, 500, 2000]) {
try { return await normalizeImageSourceToPayload(url) }
catch (e) {
lastErr = e
if (!/Image request failed: 5\d\d/.test(e.message)) break
await new Promise(r => setTimeout(r, delay))
}
}
throw lastErr Prevention
- Refresh signed URLs before fetching
- Retry 5xx with backoff; fail fast on 4xx
- Verify CORS and hotlink rules on the image host
When it happens
Trigger: Passing a URL that returns 404 (deleted asset), 403/401 (expired signed URL or private bucket), 410, or a 5xx; CORS preflight failures surface as fetch rejections while non-ok statuses surface here.
Common situations: Expired S3/CDN signed URLs; hotlink-protected image hosts returning 403; deleted attachments; server briefly returning 502/503; typo'd URL paths.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Example image request failed: ${resp.status}
- Network error: ${error.message}
- Image result evaluation requires at least one output image e
- Image compare evaluation requires at least two snapshots wit
- Image compare evaluation requires every compared snapshot to
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/20e2df6fe0cb8700.
Report an issue: GitHub.