nexu-io/open-design · error · Error

leonardo.ai image fetch ${imgResp.status}

Error message

leonardo.ai image fetch ${imgResp.status}

What it means

Thrown after a successful generation when the GET to download the generated image bytes from imageUrl returned a non-2xx status. The image URL comes from generation.generated_images[0].url (a Leonardo CDN link). The message reports the raw HTTP status so you can distinguish auth (401/403) from gone (404/410) from CDN 5xx.

Source

Thrown at apps/daemon/src/media/index.ts:2289

    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`,
    suggestedExt: sniffImageExt(bytes),
  };
}


async function renderGrokVideo(ctx: MediaContext, credentials: ProviderConfig, onProgress?: ProgressFn): Promise<RenderResult> {
  if (!credentials.apiKey) {
    throw new Error(
      'no xAI credentials — sign in with your SuperGrok subscription (in OD or via `hermes auth add xai-oauth`), set XAI_API_KEY, or configure a key in Settings',
    );
  }

View on GitHub (pinned to 5be4028344)

Solutions

  1. Retry the render — expired signed URLs and CDN 5xx usually resolve on a second attempt.
  2. If 404/410: the generated image was purged before download — re-run the generation.
  3. Verify daemon host can reach the Leonardo image CDN (network egress rules).
  4. If persistent, file a Leonardo support ticket — image lost between generation and storage is an upstream defect.

Example fix

// before
const imgResp = await fetch(imageUrl, withMediaRequestInit(ctx));
if (!imgResp.ok) {
  throw new Error(`leonardo.ai image fetch ${imgResp.status}`);
}

// after — retry transient failures before throwing
async function fetchImageBytes(url: string, attempts = 3): Promise<Buffer> {
  for (let i = 0; i < attempts; i++) {
    const r = await fetch(url);
    if (r.ok) return Buffer.from(await r.arrayBuffer());
    if (r.status >= 500 && i < attempts - 1) { await new Promise(res => setTimeout(res, 1500 * (i + 1))); continue; }
    throw new Error(`leonardo.ai image fetch ${r.status}`);
  }
  throw new Error('leonardo.ai image fetch exhausted retries');
}
Defensive patterns

Strategy: retry

Try / catch

// Image fetch failures are dominated by transient CDN 5xx and expired signed
// URLs — retry with backoff, bail on 4xx that won't self-heal.
async function fetchLeonardoImage(url: string, attempts = 3): Promise<Buffer> {
  let last: Error | null = null;
  for (let i = 0; i < attempts; i++) {
    const r = await fetch(url);
    if (r.ok) return Buffer.from(await r.arrayBuffer());
    last = new Error(`leonardo.ai image fetch ${r.status}`);
    if (r.status >= 500 && i < attempts - 1) { await new Promise(res => setTimeout(res, 1500 * (i + 1))); continue; }
    break;
  }
  throw last!;
}

Prevention

When it happens

Trigger: Generation completed, imageUrl extracted, but fetch(imageUrl, withMediaRequestInit(ctx)) returns imgResp.ok === false. Happens when the Leonardo CDN link expired between completion and download, when CDN has a transient 5xx, or when egress to the CDN host is blocked.

Common situations: Daemon paused (e.g. on queue/backpressure) long enough that the signed CDN URL expired; Leonardo CDN maintenance (5xx); firewall blocking the image CDN host; transient CDN 503/504.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/a9aeb9032395e47a. Report an issue: GitHub.