decolua/9router · error · Error
${provider} API key required
Error message
${provider} API key required What it means
`synthesizeViaConfig` resolves the provider's TTS config from AI_PROVIDERS and its credentials. For providers whose `ttsConfig.authType` is not `none`, an API key is mandatory; missing credentials throw `${provider} API key required`. This is a client-side configuration gate before any upstream call.
Source
Thrown at open-sse/handlers/ttsProviders/index.js:39
openrouter,
gemini,
"xiaomi-mimo": xiaomiMimo,
"selfhosted-tts": selfhostedTts,
};
export function getTtsAdapter(provider) {
return SPECIAL_ADAPTERS[provider] || null;
}
// Generic config-driven dispatcher (uses ttsConfig.format)
export async function synthesizeViaConfig(provider, text, model, credentials) {
const { AI_PROVIDERS } = await import("@/shared/constants/providers");
const cfg = AI_PROVIDERS[provider]?.ttsConfig;
if (!cfg) return null;
const handler = FORMAT_HANDLERS[cfg.format];
if (!handler) return null;
const apiKey = credentials?.apiKey;
if (cfg.authType !== "none" && !apiKey) throw new Error(`${provider} API key required`);
const { PROVIDER_MODELS } = await import("open-sse/config/providerModels.js");
const ttsModels = (PROVIDER_MODELS[provider] || []).filter(m => (m.kind || m.type) === "tts");
const defaultModel = ttsModels[0]?.id || "";
const { modelId, voiceId } = parseModelVoice(model, defaultModel, "", ttsModels);
return handler({ baseUrl: cfg.baseUrl, apiKey, text, modelId, voiceId });
}
// Voice fetchers (used by /api/media-providers/tts/voices route)
export const VOICE_FETCHERS = {
"edge-tts": fetchEdgeTtsVoices,
"local-device": fetchLocalDeviceVoices,
elevenlabs: fetchElevenLabsVoices,
gemini: fetchGeminiVoices,
};
// Re-export for backward compat
export { fetchEdgeTtsVoices, fetchLocalDeviceVoices, fetchElevenLabsVoices, fetchGeminiVoices };
View on GitHub (pinned to 90b52e06ff)
Solutions
- Configure the provider's API key in the dashboard credential store (or the credentials object passed to synthesize)
- Verify AI_PROVIDERS[provider].ttsConfig.authType — only `none` providers (like the Google scrape path) work keyless
- Check the key is stored under the field the credentials resolver reads (`apiKey`), not a differently named field
- If you intended a free/local TTS, switch the model/provider to one with authType `none`
Example fix
// before
await synthesizeViaConfig({ provider: 'elevenlabs', text: 'hi', credentials: {} });
// after
await synthesizeViaConfig({ provider: 'elevenlabs', text: 'hi', credentials: { apiKey: process.env.ELEVENLABS_API_KEY } }); Defensive patterns
Strategy: validation
Validate before calling
const cfg = AI_PROVIDERS[provider]?.ttsConfig;
if (cfg && cfg.authType !== 'none' && !credentials?.apiKey) {
throw new Error(`${provider} API key must be configured before TTS calls`);
} Type guard
const hasApiKey = (c) => c != null && typeof c.apiKey === 'string' && c.apiKey.length > 0;
Try / catch
try { return await synthesizeViaConfig(opts); } catch (e) { if (e.message.endsWith('API key required')) { throw new ConfigError(`Set an API key for ${provider} in the dashboard`); } throw e; } Prevention
- Configure provider credentials during setup and verify with a health check
- Check ttsConfig.authType before selecting a provider for keyless use
- Surface the key requirement in UI before the user invokes TTS
When it happens
Trigger: Calling synthesize for a TTS provider (e.g. elevenlabs, cartesia, inworld) whose stored credentials have no `apiKey`, while that provider's ttsConfig.authType is anything other than `none`.
Common situations: Fresh install with no credentials configured; credentials saved for chat completions but the TTS-specific key field empty; using a provider like the free Google translate path whose authType is `none` vs a keyed provider confused in config; env var not imported into the credential store.
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
- Vertex: could not resolve project_id from API key. Please ad
- Upstream error (${res.status})
- Bing TTS returned empty audio
- ElevenLabs API key required
- ElevenLabs TTS returned empty audio
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/383eead0ed5150e3.
Report an issue: GitHub.