moeru-ai/airi · error · Error
Image generation timed out after 5 minutes.
Error message
Image generation timed out after 5 minutes.
What it means
Thrown by generateHeadless's polling loop for providers that do not support job callbacks. The loop polls provider.getStatus every 2 seconds and enforces a 5-minute (300000 ms) hard timeout; if the job hasn't reached 'succeeded' or 'failed' within that window, this error is raised.
Source
Thrown at apps/stage-tamagotchi/src/main/services/airi/widgets/artistry-bridge.ts:196
internalJobId: createRunId('headless'),
},
}
log.log(`[Headless] Starting generation with provider: ${requestedProvider}, model: ${params.model || 'default'}`)
const job = await provider.generate(request)
log.log(`[Headless] Job created: ${job.jobId}`)
// Polling/Wait for result
if (!supportsJobCallback(provider)) {
let isDone = false
let lastStatus = await provider.getStatus(job.jobId)
const start = Date.now()
const timeout = 1000 * 60 * 5 // 5 minutes timeout
while (!isDone) {
if (Date.now() - start > timeout) {
log.error(`[Headless] Job ${job.jobId} timed out after 5 minutes.`)
throw new Error('Image generation timed out after 5 minutes.')
}
log.log(`[Headless] Polling status for job: ${job.jobId}...`)
lastStatus = await provider.getStatus(job.jobId)
log.log(`[Headless] Status for job ${job.jobId}: ${lastStatus.status}`)
if (lastStatus.status === 'succeeded' || lastStatus.status === 'failed') {
isDone = true
}
if (!isDone) {
await new Promise(resolve => setTimeout(resolve, 2000))
}
}
if (lastStatus.status === 'failed') {
log.error(`[Headless] Job ${job.jobId} failed: ${lastStatus.error || 'Unknown error'}`)
throw new Error(lastStatus.error || 'Generation failed')
}View on GitHub (pinned to 27111382b4)
Solutions
- Check the provider backend (logs/queue) to see if the job is genuinely still running or stuck.
- Reduce input complexity (smaller resolution, fewer steps) so generation finishes within the 5-minute window.
- If longer jobs are expected, increase the timeout constant and ensure the backend can actually complete them.
- Switch to a callback-capable provider (e.g. comfyui with setJobCallback) to avoid polling-driven timeouts.
Example fix
// before const timeout = 1000 * 60 * 5 // after const timeout = (artistryConfig.get()?.generationTimeoutMin ?? 5) * 1000 * 60
Defensive patterns
Strategy: retry
Try / catch
try {
return await generateHeadless(params)
} catch (e) {
if (/timed out after 5 minutes/.test(errorMessageFrom(e) ?? '')) {
// optionally retry once or surface a 'still running' state
return { error: 'Generation exceeded the 5-minute timeout' }
}
throw e
} Prevention
- Make the timeout configurable so long jobs aren't hard-killed.
- Prefer callback-capable providers to avoid polling-driven timeouts.
- Right-size generation parameters (resolution/steps) to the timeout budget.
When it happens
Trigger: A provider's getStatus never returns a terminal status within 5 minutes — the backend is overloaded, queued behind other jobs, stuck in a 'running' state, or the status endpoint is returning a non-terminal value indefinitely.
Common situations: GPU is busy / long queue on a remote generation backend; the provider underreports progress due to a status API bug; the model is very large and genuinely needs more than 5 minutes; a network hiccup causes getStatus to keep returning a stale 'running'.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Generation timed out after 5 minutes
- Artistry provider is disabled.
- Provider '${requestedProvider}' not found.
- Generation failed
- ComfyUI disconnected during polling: ${e.message}
AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12).
Data as JSON: /api/errors/aa767eed465f62ca.
Report an issue: GitHub.