{"record":{"id":"b9de17b87a7f25c1","repo":"HeyPuter/puter","slug":"upstreammessage-elevenlabs-request-failed-sta","errorCode":null,"errorMessage":"upstreamMessage ?? `ElevenLabs request failed (status ${response.status})`","messagePattern":"upstreamMessage \\?\\? `ElevenLabs request failed \\(status (.+?)\\)`","errorType":"http","errorClass":"HttpError","httpStatus":null,"severity":"error","filePath":"src/backend/drivers/ai-tts/providers/elevenlabs/ElevenLabsTTSProvider.ts","lineNumber":130,"sourceCode":"            (detail as any)?.detail?.code ?? (detail as any)?.code;\n        const upstreamMessage =\n            // eslint-disable-next-line @typescript-eslint/no-explicit-any\n            (detail as any)?.detail?.message ?? (detail as any)?.message;\n        const legacyCode =\n            response.status >= 500\n                ? 'upstream_provider_unavailable'\n                : response.status === 401 || response.status === 403\n                  ? 'upstream_auth_failed'\n                  : response.status === 429\n                    ? 'upstream_rate_limited'\n                    : 'upstream_bad_request';\n        const exposedStatus =\n            legacyCode === 'upstream_rate_limited'\n                ? 429\n                : legacyCode === 'upstream_auth_failed'\n                  ? 500\n                  : 400;\n        throw new HttpError(\n            exposedStatus,\n            upstreamMessage ??\n                `ElevenLabs request failed (status ${response.status})`,\n            {\n                legacyCode,\n                fields: {\n                    provider: 'elevenlabs',\n                    upstreamStatus: response.status,\n                    upstreamCode,\n                },\n            },\n        );\n    }\n\n    async listVoices(): Promise<ITTSVoice[]> {\n        const res = await this.request('/v1/voices');\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        const data: any = await res.json();","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/ai-tts/providers/elevenlabs/ElevenLabsTTSProvider.ts#L112-L148","documentation":"Generic upstream-failure path in ElevenLabsTTSProvider.request. Whenever the ElevenLabs REST call returns non-2xx, the response body is parsed and re-thrown as an HttpError. legacyCode maps the upstream status (5xx -> upstream_provider_unavailable, 401/403 -> upstream_auth_failed exposed as 500, 429 -> upstream_rate_limited exposed as 429, other 4xx -> upstream_bad_request exposed as 400). The message prefers ElevenLabs' own detail.message/message; otherwise 'ElevenLabs request failed (status N)'. fields includes provider, upstreamStatus, and upstreamCode.","triggerScenarios":"ElevenLabs rejects a request: unknown/invalid voice_id (404 -> upstream_bad_request), unsupported model_id, malformed voice_settings, bad/expired xi-api-key (401/403), quota/rate limit (429), or ElevenLabs outage (5xx).","commonSituations":"Hardcoding a voice id that was deleted from the ElevenLabs account; using a model the key's tier doesn't allow; stale key; burst traffic hitting 429; transient ElevenLabs 5xx. Note the exposed 500 for 401/403 hides that the real cause is the configured key.","solutions":["Inspect fields.upstreamStatus and fields.legacyCode: 401/403 -> fix/rotate the configured elevenlabs apiKey; 429 -> back off; 4xx -> fix voice_id/model/settings; 5xx -> retry.","For voice_not_found, confirm the voiceId exists via list_voices({ provider: 'elevenlabs' }) and use a returned id.","For 429, implement exponential backoff or reduce concurrency.","Check server logs for '[ElevenLabsTTSProvider] request failed' which carries the full upstream detail.","If using a custom apiBaseUrl, confirm it points to a compatible ElevenLabs-compatible endpoint."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await driver.synthesize({ text, provider: 'elevenlabs', voice: voiceId });\n} catch (e) {\n  const code = e?.fields?.legacyCode;\n  if (code === 'upstream_rate_limited') {\n    // exponential backoff, then retry\n  } else if (code === 'upstream_auth_failed') {\n    // alert ops: configured elevenlabs key is invalid/expired\n  } else if (code === 'upstream_bad_request') {\n    // likely bad voice_id/model — re-fetch via list_voices and retry\n  } else if (code === 'upstream_provider_unavailable') {\n    // transient ElevenLabs outage — bounded retry\n  } else throw e;\n}","preventionTips":["Fetch voice ids from list_voices rather than hardcoding, so deleted voices don't cause upstream_bad_request.","Use only models present in the cost table (list_engines).","Branch on fields.legacyCode; remember upstream 401/403 is exposed as 500 (key problem).","Watch server logs for '[ElevenLabsTTSProvider] request failed' with the full upstream detail."],"tags":["elevenlabs","tts","upstream","network","rate-limit","auth"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}