nexu-io/open-design · error · Error

grok image response missing b64_json/url

Error message

grok image response missing b64_json/url

What it means

Thrown by renderGrokImage when `data.data[0]` exists but carries neither `b64_json` nor `url` — i.e. the entry object has an unexpected shape. It is the final defensive guard after the b64 and URL branches, catching upstream field renames or partial responses.

Source

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

    throw new Error(`grok image ${resp.status}: ${truncate(text, 240)}`);
  }
  let data: any;
  try {
    data = JSON.parse(text);
  } catch {
    throw new Error(`grok image non-JSON: ${truncate(text, 200)}`);
  }
  const entry = data && Array.isArray(data.data) ? data.data[0] : null;
  if (!entry) throw new Error('grok image 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(`grok image fetch ${imgResp.status}`);
    bytes = Buffer.from(await imgResp.arrayBuffer());
  } else {
    throw new Error('grok image response missing b64_json/url');
  }
  // xAI's Imagine returns JPEG by default (no format option in the API
  // surface), but PNG/WebP are technically possible. Sniff the magic
  // bytes so the on-disk extension matches reality — saving JPEG bytes
  // as `.png` confuses Finder previews and any downstream consumer that
  // trusts the extension.
  return {
    bytes,
    providerNote: `grok/${ctx.wireModel} · ${aspectRatio} · ${bytes.length} bytes`,
    suggestedExt: sniffImageExt(bytes),
  };
}

async function renderNanoBananaImage(ctx: MediaContext, credentials: ProviderConfig): Promise<RenderResult> {
  const apiKey = credentials.apiKey;
  if (!apiKey) {
    throw new Error(
      'no Nano Banana API key — configure it in Settings or set OD_NANOBANANA_API_KEY',

View on GitHub (pinned to 5be4028344)

Solutions

  1. Log/inspect the full `entry` object — it usually reveals either a moderation refusal or a renamed field.
  2. If the entry is a moderation refusal, reword ctx.prompt and retry.
  3. Confirm ctx.wireModel is an image-capable xAI model, not a text/chat model.
  4. If xAI renamed the field, extend the two-branch selector in apps/daemon/src/media/index.ts:1649-1656 to read the new key.

Example fix

// before
if (entry.b64_json) {
  bytes = Buffer.from(entry.b64_json, 'base64');
} else if (entry.url) {
  // ...
} else {
  throw new Error('grok image response missing b64_json/url');
}

// after — expose the offending entry
throw new Error(
  `grok image response missing b64_json/url: ${truncate(JSON.stringify(entry), 200)}`,
);
Defensive patterns

Strategy: type-guard

Validate before calling

// Detect moderation refusals before throwing the generic missing-field error
function extractGrokImageBytes(entry: any): Buffer {
  if (entry.b64_json) return Buffer.from(entry.b64_json, 'base64');
  if (typeof entry.url === 'string') throw new Error(`grok image requires url fetch: ${entry.url}`);
  if (entry.prompt_feedback || entry.revised_prompt || entry.error) {
    throw new Error(`grok image refused/revised: ${JSON.stringify(entry).slice(0, 200)}`);
  }
  throw new Error(`grok image entry shape unrecognized: ${JSON.stringify(entry).slice(0, 200)}`);
}

Type guard

interface GrokImageEntry { b64_json?: string; url?: string; revised_prompt?: string; prompt_feedback?: unknown; error?: unknown }
function isGrokImageEntry(v: unknown): v is GrokImageEntry {
  return typeof v === 'object' && v !== null;
}

Try / catch

try {
  bytes = extractGrokImageBytes(entry);
} catch (e) {
  ctx.onProviderRequestSettled?.({ providerId: 'grok', ok: false, error: String(e) });
  throw e;
}

Prevention

When it happens

Trigger: xAI returns `data:[{revised_prompt:...}]` with the image payload under a new field name, returns a metadata-only entry, or returns a content-moderation refusal object that omits the image fields entirely.

Common situations: Prompt triggers xAI safety filters and the entry contains only a `prompt_feedback`/`revision` object; xAI ships a revised API that renames b64_json; the model variant selected does not actually produce images.

Related errors


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