{"record":{"id":"7d9ce2d3aa641267","repo":"Hmbown/CodeWhale","slug":"speech-synthesis-failed-http-status-error-tex","errorCode":null,"errorMessage":"Speech synthesis failed: HTTP {status}: {error_text}","messagePattern":"Speech synthesis failed: HTTP (.+?): (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/client.rs","lineNumber":3384,"sourceCode":"            \"format\": audio_format.clone(),\n        });\n        if let Some(voice) = voice.as_deref() {\n            audio[\"voice\"] = json!(voice);\n        }\n\n        let body = build_speech_synthesis_body(&model, &text, instruction, audio);\n\n        let url = api_url(&self.base_url, \"chat/completions\");\n        let response = self.send_json_with_retry(&url, &body).await?;\n        let status = response.status();\n        if !status.is_success() {\n            let raw_error_text = bounded_error_text(response, ERROR_BODY_MAX_BYTES).await;\n            let error_text = sanitize_http_error_body(\n                Some(self.api_provider.display_name()),\n                status.as_u16(),\n                &raw_error_text,\n            );\n            anyhow::bail!(\"Speech synthesis failed: HTTP {status}: {error_text}\");\n        }\n\n        let response_text = response\n            .text()\n            .await\n            .context(\"Failed to read speech synthesis response body\")?;\n        let payload: Value = serde_json::from_str(&response_text)\n            .context(\"Failed to parse speech synthesis response JSON\")?;\n        let (audio_bytes, transcript) = parse_speech_audio_response(&payload)?;\n\n        Ok(SpeechSynthesisResponse {\n            model,\n            audio_format,\n            audio_bytes,\n            transcript,\n            voice,\n        })\n    }","sourceCodeStart":3366,"sourceCodeEnd":3402,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/client.rs#L3366-L3402","documentation":"The speech synthesis HTTP request completed but the provider returned a non-success status. The client reads a bounded slice of the error body, passes it through `sanitize_http_error_body` (provider-attributed and redacted), and surfaces the provider's status and message so the real cause (auth, quota, bad voice payload, unsupported format) is visible. Raised in `crates/tui/src/client.rs` around line 3384.","triggerScenarios":"Any non-2xx response from POST `{base_url}/chat/completions` for a speech synthesis request: invalid API key, exhausted credits/quota, malformed voice data URI, unsupported `audio_format`, model not available to the account.","commonSituations":"Expired or missing provider API keys; free-tier accounts hitting a model they cannot access; oversized or corrupt clone audio; region-restricted endpoints returning 403.","solutions":["Read the sanitized `error_text` in the message — it is the provider's own error payload; fix the cause it names.","Verify the provider API key and account access to the requested model.","Check quota/billing if the status is 402/429.","For 4xx validation errors, check the audio format and voice payload."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"assert!(voice.as_deref().map(str::trim).filter(|v| !v.is_empty()).is_some(), \"voice required\");\nassert!([\"mp3\", \"wav\"].contains(&audio_format.as_str()), \"unsupported audio format\");","typeGuard":null,"tryCatchPattern":"match client.synthesize_speech(req).await {\n    Err(e) if e.to_string().contains(\"Speech synthesis failed: HTTP\") => {\n        let status = extract_status(&e.to_string());\n        match status {\n            429 | 503 => retry_with_backoff(),\n            401 | 403 => refresh_credentials(),\n            _ => report_provider_error(&e),\n        }\n    }\n    Err(e) => return Err(e),\n    Ok(resp) => resp,\n}","preventionTips":["Check API key validity and model entitlement before synthesis calls.","Respect rate limits with backoff on 429.","Validate the voice data URI and audio format client-side."],"tags":["http","network","api"],"backgroundTag":"http-error-response","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}