nexu-io/open-design · error · Error
leonardo.ai generation failed
Error message
leonardo.ai generation failed
What it means
Thrown when a Leonardo poll returns generation.status === 'FAILED'. This is the upstream terminal-failure signal — Leonardo accepted the job and then internally failed it (content-policy, model error, moderation). Distinct from [467] (transport failure) and [469] (no answer in time): this is a definitive negative answer.
Source
Thrown at apps/daemon/src/media/index.ts:2278
'authorization': `Bearer ${credentials.apiKey}`,
},
}));
if (!pollResp.ok) {
throw new Error(`leonardo.ai poll ${pollResp.status}`);
}
const pollData = (await pollResp.json()) as Record<string, any>;
const generation = pollData?.generations_by_pk;
if (generation?.status === 'COMPLETE') {
const images = generation?.generated_images;
if (Array.isArray(images) && images.length > 0) {
imageUrl = images[0]?.url;
break;
}
} else if (generation?.status === 'FAILED') {
throw new Error('leonardo.ai generation failed');
}
}
if (!imageUrl) {
throw new Error('leonardo.ai generation timed out after 2 minutes');
}
// Fetch the generated image
const imgResp = await fetch(imageUrl, withMediaRequestInit(ctx));
if (!imgResp.ok) {
throw new Error(`leonardo.ai image fetch ${imgResp.status}`);
}
const bytes = Buffer.from(await imgResp.arrayBuffer());
return {
bytes,
providerNote: `leonardo.ai/${ctx.model} · ${ctx.aspect} · ${bytes.length} bytes`,View on GitHub (pinned to 5be4028344)
Solutions
- Rephrase the prompt to avoid content that may trip moderation; remove explicit/sensitive terms and retry.
- Try a different Leonardo model (e.g. switch from Phoenix to FLUX) — some failures are model-specific.
- Retry once — model crashes and intermittent content-filter false positives often succeed on a second attempt.
- If failures are persistent and the prompt is benign, file a Leonardo support ticket with the generationId.
Example fix
// before
if (generation?.status === 'FAILED') {
throw new Error('leonardo.ai generation failed');
}
// after — surface upstream reason if present
if (generation?.status === 'FAILED') {
const reason = generation?.error_message || generation?.failure_reason || 'no reason returned';
throw new Error(`leonardo.ai generation failed: ${reason}`);
} Defensive patterns
Strategy: try-catch
Try / catch
// Distinguish content-policy FAILED from transient model FAILED so the caller
// can retry the latter but not the former.
if (generation?.status === 'FAILED') {
const reason = String(generation?.error_message || generation?.failure_reason || '').toLowerCase();
const err = new Error(`leonardo.ai generation failed: ${reason || 'no reason returned'}`);
(err as any).retryable = /timeout|temporary|server|unknown/.test(reason);
throw err;
} Prevention
- Surface generation.error_message in the thrown error so users can tell moderation from model crashes — the current fixed string forces them to file a ticket to learn why.
- Run a moderation pre-check on the prompt for production pipelines that can't afford a FAILED after 2 minutes of polling.
- Track FAILED rate per model in observability; a spike usually means an upstream regression or a content-policy boundary shift.
When it happens
Trigger: Polling loop receives 200 with { generations_by_pk: { status: 'FAILED' } }. Commonly caused by prompts that trip Leonardo's content filters, unsupported parameter combinations, or upstream model crashes.
Common situations: Prompt contains content Leonardo's moderation blocks; requested model + size + guidance combination Leonardo's backend can't satisfy; transient Leonardo model crash; safety filter false-positive on benign prompt.
Related errors
- grok task ${lastStatus}: ${reason}
- openai response had neither b64_json nor url
- ${providerTag} response had neither b64_json nor url
- volcengine task ${lastStatus}: ${reason}
- no Leonardo.ai API key — configure it in Settings or set LEO
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/2344a4d52c76c59b.
Report an issue: GitHub.