moeru-ai/airi · error · Error
Failed to fetch image: ${response.statusText}
Error message
Failed to fetch image: ${response.statusText} What it means
Thrown by downloadImageAsBase64 when fetch(url) returns a non-ok HTTP response while downloading a generated image for the artistry bridge. The error carries the response's statusText so the caller can see what the image host returned.
Source
Thrown at apps/stage-tamagotchi/src/main/services/airi/widgets/artistry-bridge.ts:85
*/
const cardDefaults: ArtistrySyncSnapshot = {
provider: undefined as string | undefined,
model: undefined as string | undefined,
promptPrefix: undefined as string | undefined,
options: undefined as Record<string, unknown> | undefined,
globals: undefined as Record<string, unknown> | undefined,
}
function createRunId(widgetId: string) {
return `${widgetId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`
}
async function downloadImageAsBase64(url: string): Promise<string> {
try {
log.log(`[Artistry Bridge] Downloading image from: ${url}`)
const response = await fetch(url)
if (!response.ok)
throw new Error(`Failed to fetch image: ${response.statusText}`)
const buffer = await response.arrayBuffer()
const base64 = Buffer.from(buffer).toString('base64')
// NOTICE: Downstream renderer paths consume this via fetch(), which requires a data URL.
return `data:image/png;base64,${base64}`
}
catch (error: unknown) {
log.error(`[Artistry Bridge] Failed to download image: ${errorMessageFrom(error)}`)
throw error
}
}
function supportsJobCallback(provider: ArtistryProvider): provider is ArtistryProvider & Required<Pick<ArtistryProvider, 'setJobCallback'>> {
return typeof provider.setJobCallback === 'function'
}
// Maintaining a registry of providers
export const artistryProviders = new Map<string, ArtistryProvider>()
artistryProviders.set('comfyui', new ComfyUIProvider())View on GitHub (pinned to 27111382b4)
Solutions
- Check response.status/statusText in the logs to identify the HTTP failure code, then address that code (refresh token for 401, fix URL for 404, etc.).
- If the URL is pre-signed/expiring, download the image sooner after generation or configure the provider for a longer link TTL.
- Ensure the Electron main process network environment (proxy, DNS, certs) can reach the image host.
- Add a retry with backoff for transient 5xx responses.
Example fix
// before
const response = await fetch(url)
if (!response.ok)
throw new Error(`Failed to fetch image: ${response.statusText}`)
// after
const response = await fetchWithRetry(url, { retries: 3 })
if (!response.ok)
throw new Error(`Failed to fetch image after retries: ${response.status} ${response.statusText}`) Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: only attempt download for reachable, ok URLs
async function isImageReachable(url: string): Promise<boolean> {
try {
const head = await fetch(url, { method: 'HEAD' })
return head.ok
} catch {
return false
}
} Try / catch
async function downloadWithRetry(url: string, attempts = 3): Promise<string> {
let lastErr: unknown
for (let i = 0; i < attempts; i++) {
try {
return await downloadImageAsBase64(url)
} catch (e) {
lastErr = e
await new Promise(r => setTimeout(r, 1000 * (i + 1)))
}
}
throw lastErr
} Prevention
- Download generated images promptly before pre-signed links expire.
- Ensure the Electron main process has the same network access (proxy/DNS) as the renderer.
- Log response.status alongside statusText for richer diagnostics.
When it happens
Trigger: After a provider reports a succeeded job with an imageUrl, downloadImageAsBase64 fetches that URL; if the host returns 4xx/5xx (expired link, 404, auth failure, server error) the error is thrown.
Common situations: The image URL is a temporary/pre-signed link that expired between generation and download; the provider host is behind auth not available to the Electron main process; a CDN returns 403/404; network proxy or DNS issues cause a 502/503; the URL is localhost-served but the port is wrong.
Related errors
- HTTP ${resp.status}
- Cannot connect to ComfyUI at ${this.serverUrl}: ${e.message}
- ComfyUI disconnected during polling: ${e.message}
- ComfyUI upload failed: ${error}
- No output received from Replicate.
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/82c40297e325b311.
Report an issue: GitHub.