nexu-io/open-design · error · Error
xai tts response had zero bytes
Error message
xai tts response had zero bytes
What it means
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.
Source
Thrown at apps/daemon/src/media/index.ts:2509
language,
};
const resp = await fetch(`${baseUrl}/tts`, withMediaRequestInit(ctx, {
method: 'POST',
headers: {
authorization: `Bearer ${credentials.apiKey}`,
'content-type': 'application/json',
},
body: JSON.stringify(body),
}));
if (!resp.ok) {
const errText = await resp.text().catch(() => '');
throw new Error(`xai tts ${resp.status}: ${truncate(errText, 240)}`);
}
const arrayBuffer = await resp.arrayBuffer();
const bytes = Buffer.from(arrayBuffer);
if (bytes.length === 0) {
throw new Error('xai tts response had zero bytes');
}
return {
bytes,
providerNote: `xai/${ctx.wireModel} · voice=${voiceId} · ${language} · ${bytes.length} bytes`,
suggestedExt: '.mp3',
};
}
// ---------------------------------------------------------------------------
// Provider: ElevenLabs — v3 text-to-speech (synchronous).
//
// Docs: https://elevenlabs.io/docs/api-reference/text-to-speech/convert
// The API returns MP3 bytes directly. The catalogue id `elevenlabs-v3`
// maps to the wire model `eleven_v3`, while `--voice` selects the
// voice id in the path.
// ---------------------------------------------------------------------------
const ELEVENLABS_DEFAULT_BASE_URL = 'https://api.elevenlabs.io';View on GitHub (pinned to 5be4028344)
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
Defensive patterns
Strategy: retry
Type guard
function isXaiTtsEmptyBody(err: unknown): boolean {
return err instanceof Error && err.message === 'xai tts response had zero bytes';
} Try / catch
let lastErr;
for (let attempt = 0; attempt < 2; attempt++) {
try {
return await renderXAITTS(ctx, credentials);
} catch (err) {
lastErr = err;
if (!(err instanceof Error) || err.message !== 'xai tts response had zero bytes') throw err;
}
}
throw lastErr; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- xai tts ${resp.status}: ${truncate(errText, 240)}
- openai speech returned zero bytes
- Cloudflare reported an unknown asset hash: ${hash}
- Cloudflare returned a non-JSON response.
- Vercel returned a non-JSON response.
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/c1c3942178bdfc8a.
Report an issue: GitHub.