HeyPuter/puter · error · HttpError
internal_error
internal_error
Error message
ElevenLabs API key not configured
What it means
The call reached the ElevenLabs code path but this.#apiKey is null: config.providers.elevenlabs had no apiKey (nor api_key/key) when onServerStart ran at boot. The driver throws 500 / internal_error because a missing server-side credential is an operator defect, not a caller mistake. It fires AFTER the test_mode short-circuit, so a test call still succeeds without a key.
Source
Thrown at src/backend/drivers/ai-speech2speech/VoiceChangerDriver.ts:133
!PROVIDERS.includes(
args.provider
.trim()
.toLowerCase() as (typeof PROVIDERS)[number],
)
) {
throw new HttpError(
400,
`Speech-to-speech provider not found: ${args.provider}. Available: ${PROVIDERS.join(', ')}`,
{ legacyCode: 'bad_request' },
);
}
if (args.test_mode) {
return { url: SAMPLE_AUDIO_URL, content_type: 'audio/mpeg' };
}
if (!this.#apiKey) {
throw new HttpError(500, 'ElevenLabs API key not configured', {
legacyCode: 'internal_error',
});
}
const actor = Context.get('actor');
if (!actor)
throw new HttpError(401, 'Authentication required', {
legacyCode: 'unauthorized',
});
if (!args.audio) {
throw new HttpError(400, '`audio` is required', {
legacyCode: 'bad_request',
});
}
const loaded = await loadFileInput(
this.stores,View on GitHub (pinned to 908ec23eda)
Solutions
- Set providers.elevenlabs.apiKey (or api_key / key) in the backend config and restart so onServerStart re-reads it.
- Verify the config file the running process actually loads (not a stale transpiled build).
- Until configured, call with test_mode: true to return the sample audio URL, or disable the feature in the UI.
Example fix
// config.json
// before
"providers": { "elevenlabs": {} }
// after
"providers": { "elevenlabs": { "apiKey": "xi-..." } } Defensive patterns
Strategy: validation
Validate before calling
// probe the path without spending credits
await driver.convert({ ...args, test_mode: true });
// if the test call returns sample audio but a real call 500s with
// 'ElevenLabs API key not configured', the key is missing at the server Try / catch
try {
await driver.convert(args);
} catch (e) {
if (e?.legacyCode === 'internal_error' && /API key not configured/.test(e?.message ?? '')) {
showFeatureUnavailable('speech-to-speech'); // alert ops
} else throw e;
} Prevention
- Health-check upstream credentials at boot, not at first user call.
- Keep the test_mode plumbing so the path is exercisable without a key.
- Document the config key names the loader actually accepts (apiKey/api_key/key).
When it happens
Trigger: Any real (test_mode falsy) convert() on a deployment whose config.providers.elevenlabs block is absent or has no key field, or whose key resolved to an empty/falsy string.
Common situations: Self-hosted Puter without ElevenLabs credentials in config.json; the env var never wired into the config loader; key field named with an unexpected casing the lookup (apiKey/api_key/key) does not catch.
Related errors
AI-assisted analysis of HeyPuter/puter@908ec23eda (2026-08-12).
Data as JSON: /api/errors/6836233277aeef51.
Report an issue: GitHub.