ElevenLabs Common Errors
Overview
Quick diagnostic reference for ElevenLabs API errors organized by HTTP status code: run the connectivity probe, map the observed status code to a fix, then confirm with the debug checklist. This file is the fast index; the full per-error catalog (payloads + code fixes for every status code) lives in references/error-reference.md.
Prerequisites
- ElevenLabs SDK installed
- API key configured (
ELEVENLABS_API_KEY) - Access to error logs or console output
Instructions
Step 1: Quick Diagnostic
Run the connectivity probe to isolate auth from quota from request problems:
# Test API connectivity and auth
curl -s -w "\nHTTP %{http_code}" \
https://api.elevenlabs.io/v1/user \
-H "xi-api-key: ${ELEVENLABS_API_KEY}"
# Check character quota
curl -s https://api.elevenlabs.io/v1/user \
-H "xi-api-key: ${ELEVENLABS_API_KEY}" | \
jq '.subscription | {tier, character_count, character_limit}'
# List available voices (confirms API access)
curl -s https://api.elevenlabs.io/v1/voices \
-H "xi-api-key: ${ELEVENLABS_API_KEY}" | jq '.voices | length'
Step 2: Map the Status Code to a Fix
Match the HTTP status code (and the detail.status string in the response body)
to its row below, then open the linked catalog entry for the exact payload and
copy-paste fix:
| Status | detail.status |
Root cause | First move |
|---|---|---|---|
| 401 | invalid_api_key |
Key missing/malformed/revoked | Re-check ELEVENLABS_API_KEY, regenerate if needed |
| 401 | quota_exceeded |
Monthly character limit hit | Check usage, upgrade or enable usage-based billing |
| 400 | voice_not_found |
Bad voice_id in path |
GET /v1/voices to list valid IDs |
| 400 | text_too_long |
TTS text > 5,000 chars | Chunk text with previous_text/next_text |
| 400 | model_not_found |
Bad model_id string |
Use an exact model ID (see catalog) |
| 429 | too_many_concurrent_requests |
Over plan concurrency | Queue requests to your plan limit |
| 429 | system_busy |
ElevenLabs under load | Retry with backoff (maxRetries) |
| 422 | invalid_voice_sample |
Clone audio bad format/too short | MP3/WAV/M4A/FLAC, ≥30s, clean speech |
| — | WebSocket fails silently | Missing xi_api_key / eleven_v3 on WS |
Send key in first WS message, use eleven_flash_v2_5 |
Full payloads, causes, and fix snippets for every row: references/error-reference.md.
Step 3: Debug Checklist
- Verify API key:
curl -s https://api.elevenlabs.io/v1/user -H "xi-api-key: $ELEVENLABS_API_KEY" - Check quota: Look at
character_countvscharacter_limitin the response - Verify voice_id:
GET /v1/voicesto list valid IDs - Check model_id: Must be an exact match (see catalog)
- Check request size: Text must be under 5,000 characters
- Check concurrency: Are you exceeding your plan's concurrent limit?
- Check ElevenLabs status: https://status.elevenlabs.io
Output
Working through this skill produces:
- A resolved HTTP status code and
detail.statusstring identifying the exact failure. - The applied fix (corrected key/quota, valid
voice_id/model_id, chunked text, request queue, or WebSocket handshake correction). - A clean re-run of the Step 1 probe returning
HTTP 200from/v1/userand a non-zero voice count, confirming the request path is healthy.
Error Handling
| HTTP | Error | Retryable | Action |
|---|---|---|---|
| 400 | Bad request | No | Fix request parameters |
| 401 | Auth/quota | No | Check key or upgrade plan |
| 404 | Not found | No | Verify voice_id/model_id |
| 422 | Validation | No | Fix input data format |
| 429 | Rate limit | Yes | Backoff + queue requests |
| 500+ | Server error | Yes | Retry with backoff |
Examples
401 after key rotation — the probe returns HTTP 401 with
invalid_api_key. The old key is still in the shell env:
echo "${ELEVENLABS_API_KEY:0:8}..." # confirms which key is loaded
# export the freshly generated key, then re-run the Step 1 probe → HTTP 200
429 under load — batch TTS returns too_many_concurrent_requests. Cap
concurrency to the plan limit instead of firing all requests at once:
import PQueue from "p-queue";
const queue = new PQueue({ concurrency: 5 }); // Match your plan
await queue.add(() => client.textToSpeech.convert(voiceId, options));
400 on long input — a 7,000-character request returns text_too_long.
Split it and preserve prosody across chunks:
const audio = await client.textToSpeech.convert(voiceId, {
text: currentChunk,
previous_text: previousChunk, // Helps maintain flow
next_text: nextChunk, // Helps maintain flow
model_id: "eleven_multilingual_v2",
});
See references/error-reference.md for the full payload and fix for every status code above.
Resources
Next Steps
For comprehensive debugging, see elevenlabs-debug-bundle. For rate limit handling, see elevenlabs-rate-limits.