{"record":{"id":"40847f39b47b7c94","repo":"nexu-io/open-design","slug":"providertag-non-json-response-truncate-text","errorCode":null,"errorMessage":"${providerTag} non-JSON response: ${truncate(text, 200)}","messagePattern":"(.+?) non-JSON response: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":1133,"sourceCode":"function customImageOverridesOpenAIModel(\n  ctx: MediaContext,\n  credentials: ProviderConfig | null,\n): credentials is ProviderConfig {\n  const baseUrl = credentials?.baseUrl?.trim();\n  const model = credentials?.model?.trim();\n  if (!baseUrl || !model) return false;\n  return model === ctx.model || model === ctx.wireModel;\n}\n\nasync function parseOpenAICompatibleJson(resp: Response, providerTag: string): Promise<any> {\n  const text = await resp.text();\n  if (!resp.ok) {\n    throw new Error(`${providerTag} ${resp.status}: ${truncate(text, 240)}`);\n  }\n  try {\n    return JSON.parse(text);\n  } catch {\n    throw new Error(`${providerTag} non-JSON response: ${truncate(text, 200)}`);\n  }\n}\n\nasync function bytesFromOpenAICompatibleData(data: any, providerTag: string, requestInit: MediaRequestInit = {}): Promise<Buffer> {\n  const entry = data && Array.isArray(data.data) ? data.data[0] : null;\n  if (!entry) throw new Error(`${providerTag} response had no data[0]`);\n  if (typeof entry.b64_json === 'string' && entry.b64_json) {\n    const raw = entry.b64_json.includes(',')\n      ? entry.b64_json.slice(entry.b64_json.indexOf(',') + 1)\n      : entry.b64_json;\n    return Buffer.from(raw, 'base64');\n  }\n  if (typeof entry.url === 'string' && entry.url) {\n    const mediaResp = await fetch(entry.url, requestInit);\n    if (!mediaResp.ok) {\n      throw new Error(`${providerTag} media fetch ${mediaResp.status}`);\n    }\n    const arr = await mediaResp.arrayBuffer();","sourceCodeStart":1115,"sourceCodeEnd":1151,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L1115-L1151","documentation":"Thrown by parseOpenAICompatibleJson when resp.ok is true but the body is not parseable as JSON. Same shape as the first-party 'openai non-JSON response' but for any provider routed through the shared helper. The providerTag prefix identifies which integration returned the bad body.","triggerScenarios":"Gateway returns an HTML block/landing page with HTTP 200; corporate proxy intercepts and rewrites the response; baseUrl points at a browser UI rather than the API; the gateway returns SSE or plain text on success for some models.","commonSituations":"Wrong baseUrl host; TLS-intercepting proxy; gateway that streams responses instead of returning a single JSON document.","solutions":["Inspect the inlined body snippet to identify what is returning non-JSON (HTML page, plain text, SSE chunk).","Point baseUrl at the gateway's JSON API root, not its UI or docs host.","Bypass or reconfigure intercepting proxies for the gateway host.","If the gateway streams, switch to a model/endpoint that returns a single JSON body, or extend the renderer to parse the stream."],"exampleFix":"// before\nOD_IMAGEROUTER_BASE_URL=https://imagerouter.io/\n// after (API root, not marketing site)\nOD_IMAGEROUTER_BASE_URL=https://api.imagerouter.io/v1/openai","handlingStrategy":"try-catch","validationCode":"function isCompatibleJsonEndpoint(baseUrl: string): boolean {\n  return /\\/v\\d+$/.test(baseUrl) || /api\\./.test(baseUrl);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await parseOpenAICompatibleJson(resp, providerTag);\n} catch (err) {\n  const m = err instanceof Error ? err.message : '';\n  if (m.includes('non-JSON response')) {\n    throw new ConfigError(`${providerTag} returned non-JSON. Check baseUrl and intercepting proxies. Body: ${m}`);\n  }\n  throw err;\n}","preventionTips":["Point baseUrl at the gateway's API JSON root, not its UI or docs host.","Bypass TLS-intercepting proxies for the gateway host or whitelist its API path.","Confirm the gateway returns a single JSON document, not an SSE stream."],"tags":["network","media","openai-compatible","response-shape","proxy"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}