{"record":{"id":"c1c3942178bdfc8a","repo":"nexu-io/open-design","slug":"xai-tts-response-had-zero-bytes","errorCode":null,"errorMessage":"xai tts response had zero bytes","messagePattern":"xai tts response had zero bytes","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":2509,"sourceCode":"    language,\n  };\n\n  const resp = await fetch(`${baseUrl}/tts`, 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  if (!resp.ok) {\n    const errText = await resp.text().catch(() => '');\n    throw new Error(`xai tts ${resp.status}: ${truncate(errText, 240)}`);\n  }\n  const arrayBuffer = await resp.arrayBuffer();\n  const bytes = Buffer.from(arrayBuffer);\n  if (bytes.length === 0) {\n    throw new Error('xai tts response had zero bytes');\n  }\n  return {\n    bytes,\n    providerNote: `xai/${ctx.wireModel} · voice=${voiceId} · ${language} · ${bytes.length} bytes`,\n    suggestedExt: '.mp3',\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Provider: ElevenLabs — v3 text-to-speech (synchronous).\n//\n// Docs: https://elevenlabs.io/docs/api-reference/text-to-speech/convert\n// The API returns MP3 bytes directly. The catalogue id `elevenlabs-v3`\n// maps to the wire model `eleven_v3`, while `--voice` selects the\n// voice id in the path.\n// ---------------------------------------------------------------------------\n\nconst ELEVENLABS_DEFAULT_BASE_URL = 'https://api.elevenlabs.io';","sourceCodeStart":2491,"sourceCodeEnd":2527,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L2491-L2527","documentation":"Thrown by renderXAITTS() when the POST /tts returned HTTP 2xx but the response body buffer is zero bytes. xAI's documented success response is raw audio bytes, so an empty 2xx body means the provider returned an unusable response. There is no JSON error to surface, so this distinct guard catches the silent failure.","triggerScenarios":"xAI returns 200 OK with an empty body — a transient provider fault, a streaming misconfiguration, or a content-filter that suppressed all audio without an error status.","commonSituations":"Transient xAI backend issue; prompt triggered a content filter that produced no audio; intermediary proxy stripped the body; rare provider bug after a model rollout.","solutions":["Retry the same request once — empty-body 2xx is usually transient","If it persists, simplify the prompt to rule out content filtering, then retry","Check whether a proxy or custom baseUrl is mangling the response body","Report to xAI if it reproduces with curl against https://api.x.ai/v1/tts"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"function isXaiTtsEmptyBody(err: unknown): boolean {\n  return err instanceof Error && err.message === 'xai tts response had zero bytes';\n}","tryCatchPattern":"let lastErr;\nfor (let attempt = 0; attempt < 2; attempt++) {\n  try {\n    return await renderXAITTS(ctx, credentials);\n  } catch (err) {\n    lastErr = err;\n    if (!(err instanceof Error) || err.message !== 'xai tts response had zero bytes') throw err;\n  }\n}\nthrow lastErr;","preventionTips":["Treat empty-2xx as transient and retry once before surfacing","Log the prompt length and voice id alongside the failure to spot content-filter patterns","Alert if the empty-body rate exceeds a threshold — it usually indicates a provider incident"],"tags":["xai","tts","upstream","empty-response"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}