nexu-io/open-design · error · Error

openai image fetch ${imgResp.status}

Error message

openai image fetch ${imgResp.status}

What it means

Thrown by renderOpenAIImage when the response carried entry.url instead of b64_json and the secondary fetch of that URL returned a non-2xx status. OpenAI/Azure sometimes return a hosted image URL instead of inline bytes; the daemon downloads it before writing to disk, and a failure here means that download step broke, not the generation itself.

Source

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

  const text = await resp.text();
  if (!resp.ok) {
    const tag = azure ? 'azure-openai' : 'openai';
    throw new Error(`${tag} ${resp.status}: ${truncate(text, 240)}`);
  }
  let data: any;
  try {
    data = JSON.parse(text);
  } catch {
    throw new Error(`openai non-JSON response: ${truncate(text, 200)}`);
  }
  const entry = data && Array.isArray(data.data) ? data.data[0] : null;
  if (!entry) throw new Error('openai response had no data[0]');
  let bytes;
  if (entry.b64_json) {
    bytes = Buffer.from(entry.b64_json, 'base64');
  } else if (entry.url) {
    const imgResp = await fetch(entry.url, withMediaRequestInit(ctx));
    if (!imgResp.ok) throw new Error(`openai image fetch ${imgResp.status}`);
    const arr = await imgResp.arrayBuffer();
    bytes = Buffer.from(arr);
  } else {
    throw new Error('openai response had neither b64_json nor url');
  }

  const tag = azure ? 'azure-openai' : 'openai';
  return {
    bytes,
    providerNote: `${tag}/${ctx.wireModel} · ${ctx.aspect} · ${bytes.length} bytes`,
    suggestedExt: '.png',
  };
}

async function renderImageRouterImage(ctx: MediaContext, credentials: ProviderConfig): Promise<RenderResult> {
  if (!credentials.apiKey) {
    throw new Error(
      'no ImageRouter API key — configure it in Settings or set OD_IMAGEROUTER_API_KEY',

View on GitHub (pinned to 5be4028344)

Solutions

  1. Retry the request — signed URL fetches are often transient.
  2. Request b64_json output instead of url if the integration supports it (forces inline bytes, no second fetch).
  3. Allowlist the OpenAI image CDN host (e.g. *.blob.core.windows.net for Azure, files.oaiusercontent.com for OpenAI) in egress rules.
  4. Check for clock skew on the daemon host — signed URLs validate against the upstream server clock.

Example fix

// before: response_format defaults to url and CDN is blocked
// after: pin response_format to b64_json in your custom integration path
body.response_format = 'b64_json';
Defensive patterns

Strategy: retry

Try / catch

try {
  return await renderOpenAIImage(ctx, credentials);
} catch (err) {
  const m = err instanceof Error ? err.message : '';
  if (m.startsWith('openai image fetch ')) {
    // signed-URL download failed; retry once, then suggest b64_json
    await sleep(backoffMs);
    return await renderOpenAIImage(ctx, credentials);
  }
  throw err;
}

Prevention

When it happens

Trigger: OpenAI returns a signed url that expired before the follow-up fetch; the hosted-image CDN returns 403/404; a network egress filter blocks the image CDN host while allowing api.openai.com; corporate proxy allows the API but blocks the blob storage host.

Common situations: Long latency between generation and download causing URL expiry; restrictive egress firewall; transient CDN 5xx; signed-URL region mismatch.

Related errors


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