decolua/9router · error
ElevenLabs API key required
Error message
ElevenLabs API key required
What it means
fetchElevenLabsVoices requires an ElevenLabs API key (sent as the `xi-api-key` header) and throws this error immediately when called with a falsy key. It is a guard against making an authenticated list-voices call without credentials, since ElevenLabs will only reject the request later with a 401.
Source
Thrown at open-sse/handlers/ttsProviders/elevenlabs.js:8
// ElevenLabs TTS — voice id with optional model_id prefix
import { Buffer } from "node:buffer";
const VOICES_TTL = 24 * 60 * 60 * 1000;
const _voicesCache = new Map(); // by API key
export async function fetchElevenLabsVoices(apiKey) {
if (!apiKey) throw new Error("ElevenLabs API key required");
const now = Date.now();
const cached = _voicesCache.get(apiKey);
if (cached && now - cached.time < VOICES_TTL) return cached.voices;
const res = await fetch("https://api.elevenlabs.io/v1/voices", {
headers: { "xi-api-key": apiKey, "Content-Type": "application/json" },
});
if (!res.ok) throw new Error(`ElevenLabs voices fetch failed: ${res.status}`);
const data = await res.json();
// Normalize: derive lang from labels for grouping
const voices = (data.voices || []).map((v) => ({ ...v, lang: v.labels?.language || "en" }));
_voicesCache.set(apiKey, { voices, time: now });
return voices;
}
export default {
async synthesize(text, model, credentials) {
if (!credentials?.apiKey) throw new Error("ElevenLabs API key required");View on GitHub (pinned to 90b52e06ff)
Solutions
- Enter a valid ElevenLabs API key in the 9Router dashboard credentials for the ElevenLabs provider.
- Verify the credential object shape: the code reads `credentials.apiKey` — ensure your key is stored under `apiKey`, not another field name.
- Test the key directly: `curl -H "xi-api-key: $KEY" https://api.elevenlabs.io/v1/voices` should return 200.
- If calling fetchElevenLabsVoices programmatically, pass the key explicitly: fetchElevenLabsVoices(process.env.ELEVENLABS_API_KEY).
Example fix
// before
const voices = await fetchElevenLabsVoices(creds.elevenKey); // undefined field
// after
const key = creds?.apiKey || process.env.ELEVENLABS_API_KEY;
if (!key) throw new Error("Set an ElevenLabs API key before listing voices");
const voices = await fetchElevenLabsVoices(key); Defensive patterns
Strategy: validation
Validate before calling
function hasElevenLabsCredentials(creds) {
return typeof creds?.apiKey === "string" && creds.apiKey.trim().length > 0;
}
if (!hasElevenLabsCredentials(creds)) throw new Error("Configure an ElevenLabs API key first"); Type guard
function hasApiKey(creds) {
return typeof creds === "object" && creds !== null &&
typeof creds.apiKey === "string" && creds.apiKey.length > 0;
} Try / catch
try {
const voices = await fetchElevenLabsVoices(apiKey);
} catch (e) {
if (e.message === "ElevenLabs API key required") {
// surface a config error to the user, not a 500
return res.status(400).json({ error: "ElevenLabs provider is not configured — add an API key in the dashboard" });
}
throw e;
} Prevention
- Configure the ElevenLabs API key immediately after enabling the provider.
- Always store keys under the `apiKey` credential field.
- Trim keys when pasting to avoid blank/whitespace-only values.
- Add a startup health check that lists voices once to verify the key early.
When it happens
Trigger: Calling fetchElevenLabsVoices() (via the `voices` handler) with the ElevenLabs provider selected while no API key is configured — credentials missing, credentials present but the key field named incorrectly (e.g. `token` instead of `apiKey`), or an empty-string key stored in the dashboard.
Common situations: User enabled the ElevenLabs TTS provider in 9Router but never entered an API key; key stored under the wrong credential field after migration; key was deleted/blanked in the credentials UI; code path invoked programmatically without passing credentials.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
- No Gemini API key configured
- No OpenAI API key configured
- No OpenRouter API key configured
- xiaomi-mimo API key required
- Upstream error (${res.status})
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/7b97472c4ae3edc5.
Report an issue: GitHub.