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

  1. Retry the same request once — empty-body 2xx is usually transient
  2. If it persists, simplify the prompt to rule out content filtering, then retry
  3. Check whether a proxy or custom baseUrl is mangling the response body
  4. 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

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


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/c1c3942178bdfc8a. Report an issue: GitHub.