decolua/9router · error · Error

ElevenLabs TTS returned empty audio

Error message

ElevenLabs TTS returned empty audio

What it means

After a 200 response, ElevenLabs synthesize requires the audio body to be at least 1024 bytes before returning base64 MP3; anything smaller throws "ElevenLabs TTS returned empty audio". This catches responses that succeeded at the HTTP layer but contain no usable audio payload.

Solutions

  1. Check that the input text is non-empty after trimming before calling synthesize.
  2. Retry the request once — brief upstream truncation is usually transient.
  3. If the text is genuinely tiny (a single word), the <1KB threshold may false-positive; test the same text with a longer string to confirm, and consider treating the payload as valid.
  4. Check ElevenLabs status/your account quota; some degraded modes return empty audio with 200.
  5. Fall back to another TTS provider for the affected request.

Example fix

// before
await elevenlabs.synthesize(text, model, creds); // text may be ""
// after
const t = (text || "").trim();
if (!t) throw new Error("TTS text is empty");
await elevenlabs.synthesize(t, model, creds);
Defensive patterns

Strategy: validation

Validate before calling

if (!text?.trim()) throw new Error("TTS text is empty");
if (text.trim().length < 1) throw new Error("TTS text too short to synthesize");

Type guard

function isSynthesizableText(t) {
  return typeof t === "string" && t.trim().length > 0;
}

Try / catch

try {
  const audio = await elevenlabs.synthesize(text, model, creds);
} catch (e) {
  if (e.message === "ElevenLabs TTS returned empty audio") {
    // transient upstream issue — retry once, then fall back
    try { return await elevenlabs.synthesize(text, model, creds); }
    catch { return await fallbackTts(text); }
  }
  throw e;
}

Prevention

When it happens

Trigger: ElevenLabs returns 200 with a tiny body — usually an empty or near-empty response when the voice/model produced no audio, a truncated response on connection issues, or when the request contained empty/whitespace text so nothing was synthesized.

Common situations: Passing empty or whitespace-only text through the pipeline; extremely short text with certain voices producing sub-1KB payloads at low bitrates; ElevenLabs-side incidents returning empty 200s; chunked-response truncation through a proxy.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/9adaf09362f296e9. Report an issue: GitHub.

Appendix: source

Thrown at open-sse/handlers/ttsProviders/elevenlabs.js:45

    let modelId = "eleven_flash_v2_5";
    let voiceId = model;
    if (model && model.includes("/")) [modelId, voiceId] = model.split("/");

    const res = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`, {
      method: "POST",
      headers: { "xi-api-key": credentials.apiKey, "Content-Type": "application/json" },
      body: JSON.stringify({
        text,
        model_id: modelId,
        voice_settings: { stability: 0.5, similarity_boost: 0.75 },
      }),
    });
    if (!res.ok) {
      const err = await res.json().catch(() => ({}));
      throw new Error(err?.detail?.message || `ElevenLabs TTS failed: ${res.status}`);
    }
    const buf = await res.arrayBuffer();
    if (buf.byteLength < 1024) throw new Error("ElevenLabs TTS returned empty audio");
    return { base64: Buffer.from(buf).toString("base64"), format: "mp3" };
  },
};

View on GitHub (pinned to 90b52e06ff)