{"record":{"id":"9f41047c98754d4a","repo":"nexu-io/open-design","slug":"grok-image-response-missing-b64-json-url","errorCode":null,"errorMessage":"grok image response missing b64_json/url","messagePattern":"grok image response missing b64_json/url","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":1656,"sourceCode":"    throw new Error(`grok image ${resp.status}: ${truncate(text, 240)}`);\n  }\n  let data: any;\n  try {\n    data = JSON.parse(text);\n  } catch {\n    throw new Error(`grok image non-JSON: ${truncate(text, 200)}`);\n  }\n  const entry = data && Array.isArray(data.data) ? data.data[0] : null;\n  if (!entry) throw new Error('grok image response had no data[0]');\n  let bytes;\n  if (entry.b64_json) {\n    bytes = Buffer.from(entry.b64_json, 'base64');\n  } else if (entry.url) {\n    const imgResp = await fetch(entry.url, withMediaRequestInit(ctx));\n    if (!imgResp.ok) throw new Error(`grok image fetch ${imgResp.status}`);\n    bytes = Buffer.from(await imgResp.arrayBuffer());\n  } else {\n    throw new Error('grok image response missing b64_json/url');\n  }\n  // xAI's Imagine returns JPEG by default (no format option in the API\n  // surface), but PNG/WebP are technically possible. Sniff the magic\n  // bytes so the on-disk extension matches reality — saving JPEG bytes\n  // as `.png` confuses Finder previews and any downstream consumer that\n  // trusts the extension.\n  return {\n    bytes,\n    providerNote: `grok/${ctx.wireModel} · ${aspectRatio} · ${bytes.length} bytes`,\n    suggestedExt: sniffImageExt(bytes),\n  };\n}\n\nasync function renderNanoBananaImage(ctx: MediaContext, credentials: ProviderConfig): Promise<RenderResult> {\n  const apiKey = credentials.apiKey;\n  if (!apiKey) {\n    throw new Error(\n      'no Nano Banana API key — configure it in Settings or set OD_NANOBANANA_API_KEY',","sourceCodeStart":1638,"sourceCodeEnd":1674,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L1638-L1674","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log/inspect the full `entry` object — it usually reveals either a moderation refusal or a renamed field.","If the entry is a moderation refusal, reword ctx.prompt and retry.","Confirm ctx.wireModel is an image-capable xAI model, not a text/chat model.","If xAI renamed the field, extend the two-branch selector in apps/daemon/src/media/index.ts:1649-1656 to read the new key."],"exampleFix":"// before\nif (entry.b64_json) {\n  bytes = Buffer.from(entry.b64_json, 'base64');\n} else if (entry.url) {\n  // ...\n} else {\n  throw new Error('grok image response missing b64_json/url');\n}\n\n// after — expose the offending entry\nthrow new Error(\n  `grok image response missing b64_json/url: ${truncate(JSON.stringify(entry), 200)}`,\n);","handlingStrategy":"type-guard","validationCode":"// Detect moderation refusals before throwing the generic missing-field error\nfunction extractGrokImageBytes(entry: any): Buffer {\n  if (entry.b64_json) return Buffer.from(entry.b64_json, 'base64');\n  if (typeof entry.url === 'string') throw new Error(`grok image requires url fetch: ${entry.url}`);\n  if (entry.prompt_feedback || entry.revised_prompt || entry.error) {\n    throw new Error(`grok image refused/revised: ${JSON.stringify(entry).slice(0, 200)}`);\n  }\n  throw new Error(`grok image entry shape unrecognized: ${JSON.stringify(entry).slice(0, 200)}`);\n}","typeGuard":"interface GrokImageEntry { b64_json?: string; url?: string; revised_prompt?: string; prompt_feedback?: unknown; error?: unknown }\nfunction isGrokImageEntry(v: unknown): v is GrokImageEntry {\n  return typeof v === 'object' && v !== null;\n}","tryCatchPattern":"try {\n  bytes = extractGrokImageBytes(entry);\n} catch (e) {\n  ctx.onProviderRequestSettled?.({ providerId: 'grok', ok: false, error: String(e) });\n  throw e;\n}","preventionTips":["Branch on the actual field names xAI uses; do not assume only b64_json/url exist.","Detect and label moderation/refusal entries distinctly from shape errors so operators know to reword the prompt.","Log the unrecognized entry keys when extraction fails.","Confirm the model is image-capable before sending."],"tags":["grok","xai","image-generation","response-shape","content-moderation","provider-api"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}