nexu-io/open-design · error · Error
xai tts ${resp.status}: ${truncate(errText, 240)}
Error message
xai tts ${resp.status}: ${truncate(errText, 240)} What it means
Thrown by renderXAITTS() after POST {baseUrl}/tts returns a non-2xx response. The error embeds the HTTP status code and the first 240 characters of the response body (via truncate), so the upstream xAI error is surfaced rather than swallowed. This is the only signal of provider-side rejection (bad voice id, invalid language, rate limit, auth failure).
Source
Thrown at apps/daemon/src/media/index.ts:2504
// we want. Future work: surface sample_rate / bit_rate / codec via
// ctx so the agent can request wav for high-fidelity workflows.
const body = {
text,
voice_id: voiceId,
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`View on GitHub (pinned to 5be4028344)
Solutions
- Read the embedded status and body text: 401/403 means re-authorize via hermes auth add xai-oauth or refresh XAI_API_KEY
- For 400, check that ctx.voice (voice_id) and ctx.language are values xAI accepts; fall back to defaults (eve / en) by clearing the overrides
- For 429, back off and retry with fewer concurrent TTS requests
- For 5xx, retry after a short delay; check the xAI status page
- Confirm credentials.baseUrl is either unset (uses https://api.x.ai/v1) or points at a valid xAI-compatible endpoint
Example fix
// before: voice override that xAI rejects
const ctx = { prompt: 'hello', voice: 'nonexistent-voice', wireModel: 'grok-tts' };
// after: omit voice to use the documented default 'eve'
const ctx = { prompt: 'hello', wireModel: 'grok-tts' }; Defensive patterns
Strategy: try-catch
Type guard
function isXaiTtsHttpError(err: unknown): boolean {
return err instanceof Error && /^xai tts \d{3}:/.test(err.message);
} Try / catch
try {
const result = await renderXAITTS(ctx, credentials);
} catch (err) {
if (err instanceof Error && /^xai tts (\d{3}):/.test(err.message)) {
const status = Number(RegExp.$1);
if (status === 401 || status === 403) await refreshXaiCredentials();
else if (status === 429) await backoffThenRetry();
else throw err;
} else throw err;
} Prevention
- Validate voice_id and language against xAI's documented values before sending
- Implement token refresh on 401/403 so expired OAuth does not surface as a hard failure
- Add exponential backoff for 429 responses on batch TTS jobs
- Keep baseUrl at the default unless a verified proxy is required
When it happens
Trigger: xAI rejects the TTS request: 401/403 for bad or expired token, 400 for an unsupported voice_id or language, 429 for rate limiting, 5xx for provider outage, or a wrong baseUrl pointing at a non-xAI host.
Common situations: OAuth token expired; voice_id does not exist on the user's plan; language code not supported; baseUrl override points at a proxy that returns its own error shape; rate limit hit during batch generation; xAI incident.
Related errors
- xai tts response had zero bytes
- Cloudflare returned a non-JSON response.
- Vercel returned a non-JSON response.
- UPSTREAM_UNAVAILABLE
- aihubmix image (gemini) ${resp.status}: ${text.slice(0, 240)
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/229c999beb939a4c.
Report an issue: GitHub.