{"record":{"id":"b49d64d8ab1934c1","repo":"chenhg5/cc-connect","slug":"openai-tts-api-d-s","errorCode":null,"errorMessage":"openai tts API %d: %s","messagePattern":"openai tts API (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tts.go","lineNumber":263,"sourceCode":"\t}\n\n\turl := strings.TrimRight(o.BaseURL, \"/\") + \"/audio/speech\"\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(jsonData))\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"openai tts: create request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+o.APIKey)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := o.Client.Do(req)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"openai tts: request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\treturn nil, \"\", fmt.Errorf(\"openai tts API %d: %s\", resp.StatusCode, body)\n\t}\n\n\tmp3Data, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"openai tts: read audio: %w\", err)\n\t}\n\treturn mp3Data, \"mp3\", nil\n}\n\n// ──────────────────────────────────────────────────────────────\n// MiniMaxTTS — MiniMax T2A v2 TTS implementation\n// ──────────────────────────────────────────────────────────────\n\n// MiniMaxTTS implements TextToSpeech using the MiniMax T2A v2 API.\ntype MiniMaxTTS struct {\n\tAPIKey  string\n\tBaseURL string\n\tModel   string","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/tts.go#L245-L281","documentation":"This error is returned when the TTS endpoint responds with a non-200 HTTP status. The library reads the response body and embeds both the status code and body text so the upstream API's own error message (auth failure, invalid model, quota, bad parameter) is visible to the caller.","triggerScenarios":"Any non-200 response from POST {BaseURL}/audio/speech: 401 invalid API key, 403 forbidden, 404 wrong path/model, 429 rate limit, 5xx upstream outage.","commonSituations":"Expired or wrong OPENAI_API_KEY for the configured BaseURL, a third-party OpenAI-compatible proxy that doesn't implement /audio/speech, unsupported model/tts-1 voice parameters, exhausted quota.","solutions":["Read the status code and body in the wrapped message to identify the upstream cause","Verify the API key is valid and has TTS/quota access for the endpoint","Confirm the BaseURL points to a provider that implements /audio/speech (many proxies only proxy /chat/completions)","Back off and retry on 429/5xx; fix credentials/parameters on 401/403/400"],"exampleFix":"// before\no.BaseURL = \"https://my-proxy.example.com\" // no /v1 audio support\n// after\no.BaseURL = \"https://api.openai.com/v1\" // provider that serves /audio/speech","handlingStrategy":"try-catch","validationCode":"if cfg.TTSAPIKey == \"\" { return errors.New(\"tts api key not configured\") }","typeGuard":"null","tryCatchPattern":"mp3, format, err := tts.Synthesize(ctx, text)\nif err != nil {\n    var apiErr string\n    if strings.Contains(err.Error(), \"tts API \") {\n        apiErr = err.Error() // includes status code and upstream body\n        // 401/403 -> fix key; 429/5xx -> retry with backoff\n    }\n    return fmt.Errorf(\"tts failed: %s\", apiErr)\n}","preventionTips":["Rotate and validate API keys before deployment","Confirm the provider/proxy supports the /audio/speech endpoint","Implement backoff retry for 429 and 5xx statuses","Monitor quota usage"],"tags":["go","tts","http-error","api"],"backgroundTag":"http-error-response","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}