nexu-io/open-design · error · Error

openai response had no data[0]

Error message

openai response had no data[0]

What it means

Thrown by renderOpenAIImage after JSON parsed successfully but data is missing or data[0] is null/undefined. The OpenAI image response contract is {data:[{b64_json|url,...}]}; an empty array or absent data field means the upstream returned an unexpected (but JSON) shape, e.g. an error envelope with a 200 status or a different API version.

Source

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

    headers,
    body: JSON.stringify(body),
    dispatcher: ctx.requestInit.dispatcher
      ?? openAIImageDispatcher as unknown as NonNullable<RequestInit['dispatcher']>,
    signal: AbortSignal.timeout(Math.max(OPENAI_IMAGE_HEADERS_TIMEOUT_MS, OPENAI_IMAGE_BODY_TIMEOUT_MS)),
  }));
  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',
  };

View on GitHub (pinned to 5be4028344)

Solutions

  1. Log the full parsed JSON (the error only says data[0] is missing) to see what envelope was actually returned.
  2. Confirm baseUrl targets the images endpoint host (the path /images/generations is appended by buildOpenAIImageUrl).
  3. For Azure, ensure the deployment URL includes the api-version query parameter expected by Azure.
  4. Switch to a model id the upstream actually serves for image generation.

Example fix

// before: baseUrl pointed at chat endpoint
OD_OPENAI_BASE_URL=https://api.openai.com/v1/chat
// after
OD_OPENAI_BASE_URL=https://api.openai.com/v1
Defensive patterns

Strategy: try-catch

Validate before calling

function isOpenAIImageEnvelope(data: unknown): data is { data: [{ b64_json?: string; url?: string }] } {
  return Boolean(data && typeof data === 'object' && Array.isArray((data as any).data) && (data as any).data.length > 0);
}

Type guard

function isOpenAIImageEnvelope(data: unknown): data is { data: [{ b64_json?: string; url?: string }] } {
  return Boolean(data && typeof data === 'object' && Array.isArray((data as any).data) && (data as any).data.length > 0);
}

Try / catch

try {
  return await renderOpenAIImage(ctx, credentials);
} catch (err) {
  const m = err instanceof Error ? err.message : '';
  if (m === 'openai response had no data[0]') {
    throw new ConfigError('Upstream returned an unexpected JSON envelope. Verify baseUrl targets the images API.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Upstream returned {error:...} with HTTP 200 (misconfigured gateway); pointing baseUrl at /v1/chat/completions by mistake (different schema); API version skew where OpenAI/Azure changed the envelope; a transparent gateway that wraps responses.

Common situations: BaseUrl pointing at a chat completions endpoint; Azure API-version query string missing so a different schema is returned; using an OpenAI-compatible shim that omits the data array.

Related errors


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