{"record":{"id":"5c433d82fb546143","repo":"nexu-io/open-design","slug":"grok-video-non-json-truncate-submittext-200","errorCode":null,"errorMessage":"grok video non-JSON: ${truncate(submitText, 200)}","messagePattern":"grok video non-JSON: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":2347,"sourceCode":"  }\n\n  const submitResp = await fetch(`${baseUrl}/videos/generations`, withMediaRequestInit(ctx, {\n    method: 'POST',\n    headers: {\n      'authorization': `Bearer ${credentials.apiKey}`,\n      'content-type': 'application/json',\n    },\n    body: JSON.stringify(body),\n  }));\n  const submitText = await submitResp.text();\n  if (!submitResp.ok) {\n    throw new Error(`grok video submit ${submitResp.status}: ${truncate(submitText, 240)}`);\n  }\n  let submitData: any;\n  try {\n    submitData = JSON.parse(submitText);\n  } catch {\n    throw new Error(`grok video non-JSON: ${truncate(submitText, 200)}`);\n  }\n\n  // Two paths: (a) the API returned the finished video synchronously\n  // (cached/short jobs), in which case we skip polling; (b) we got an\n  // {id, status:'pending'} stub and need to poll GET /videos/{id}\n  // until status flips to done/failed/expired.\n  let videoUrl = submitData?.video?.url || null;\n  let lastStatus = submitData?.status || '';\n  const requestId = submitData?.id || submitData?.request_id || null;\n\n  if (!videoUrl && requestId) {\n    const startedAt = Date.now();\n    const configuredMaxMs = Number(process.env.OD_GROK_VIDEO_MAX_POLL_MS);\n    const maxMs =\n      Number.isFinite(configuredMaxMs) && configuredMaxMs >= 60_000\n        ? configuredMaxMs\n        : 8 * 60 * 1000;\n    if (typeof onProgress === 'function') {","sourceCodeStart":2329,"sourceCodeEnd":2365,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L2329-L2365","documentation":"Thrown when xAI's POST /videos/generations returned 2xx but the body failed JSON.parse. The server returned a non-JSON payload (HTML, plain text, empty) with a success status. The message includes the first 200 chars (truncated) so the operator can identify the unexpected content shape. Distinct from [472] which fires on non-2xx status.","triggerScenarios":"submitResp.ok is true but JSON.parse(submitText) throws — xAI (or an intermediary) returned 200 with an HTML page, a Cloudflare challenge, an empty body, or plain text. Often a transient gateway behavior.","commonSituations":"Cloudflare interstitial served with 200; xAI gateway returning a cached HTML error page; reverse proxy in front of api.x.ai rewriting responses; baseUrl in provider config pointing at a non-API host.","solutions":["Inspect the truncated body in the error — HTML/doctype means gateway or maintenance page; retry shortly.","If you set a custom baseUrl, confirm it points at 'https://api.x.ai/v1' (or your xAI deployment's JSON API root), not an HTML surface.","Retry with exponential backoff — interstitials are usually transient.","If persistent, capture the full response and report to xAI support."],"exampleFix":"// before — wrong baseUrl returns HTML\ncredentials.baseUrl = 'https://x.ai'\n// → 200 OK with HTML homepage → [473]\n\n// after\ncredentials.baseUrl = 'https://api.x.ai/v1'","handlingStrategy":"try-catch","validationCode":"// Reject a misconfigured baseUrl before it ever produces HTML responses.\nfunction assertGrokBaseUrl(baseUrl?: string): void {\n  if (!baseUrl) return;\n  try {\n    const u = new URL(baseUrl);\n    if (u.hostname !== 'api.x.ai' && !u.hostname.endsWith('.api.x.ai')) {\n      throw new Error(`xAI baseUrl host looks wrong (${u.hostname}); expected api.x.ai`);\n    }\n  } catch (e) { throw e; }\n}","typeGuard":null,"tryCatchPattern":"// Distinguish parse failure from real HTTP failure so the operator gets the right hint.\nlet submitData: any;\ntry {\n  submitData = JSON.parse(submitText);\n} catch {\n  const looksLikeHtml = /^\\s*<(?:!doctype|html|body)/i.test(submitText);\n  throw new Error(\n    `grok video non-JSON (${looksLikeHtml ? 'html/gateway' : 'unknown'}): ${truncate(submitText, 200)}`,\n  );\n}","preventionTips":["Validate baseUrl hostname on provider config save (reject anything that isn't api.x.ai).","Send `Accept: application/json` on all xAI requests to discourage HTML gateway responses.","Run a smoke render after any xAI config change to catch HTML-gateway regressions early."],"tags":["grok","xai","json-parse","gateway","configuration"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}