chenhg5/cc-connect · error
qwen tts: parse response: %w
Error message
qwen tts: parse response: %w
What it means
After a 200 status, Synthesize unmarshals the JSON body into the result struct (code/message/output.audio.url). If the body is not valid JSON or doesn't match the expected shape, it returns 'qwen tts: parse response'. The response succeeded at HTTP level but is not the documented envelope.
Source
Thrown at core/tts.go:170
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, "", fmt.Errorf("qwen tts: read response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, "", fmt.Errorf("qwen tts API %d: %s", resp.StatusCode, body)
}
var result struct {
Code string `json:"code"`
Message string `json:"message"`
Output struct {
Audio struct {
URL string `json:"url"`
} `json:"audio"`
} `json:"output"`
}
if err := json.Unmarshal(body, &result); err != nil {
return nil, "", fmt.Errorf("qwen tts: parse response: %w", err)
}
if result.Code != "" {
return nil, "", fmt.Errorf("qwen tts API error %s: %s", result.Code, result.Message)
}
if result.Output.Audio.URL == "" {
return nil, "", fmt.Errorf("qwen tts: empty audio URL in response")
}
// Download WAV from temporary URL
audioReq, err := http.NewRequestWithContext(ctx, http.MethodGet, result.Output.Audio.URL, nil)
if err != nil {
return nil, "", fmt.Errorf("qwen tts: create download request: %w", err)
}
audioResp, err := q.Client.Do(audioReq)
if err != nil {
return nil, "", fmt.Errorf("qwen tts: download audio: %w", err)
}
defer audioResp.Body.Close()View on GitHub (pinned to 4000b2338a)
Solutions
- Log the raw body on this failure to see what was actually returned.
- Check whether a proxy/intermediary is rewriting the response (HTML login pages, WAF blocks).
- Verify the BaseURL points at the JSON API endpoint, not a console or redirect URL.
- Confirm the provider API version still matches the response schema in core/tts.go.
Example fix
// before
// silent assumption: body is valid JSON
// after
if !json.Valid(body) {
slog.Error("qwen tts non-JSON body", "prefix", string(body[:min(200, len(body))]))
}
if err := json.Unmarshal(body, &result); err != nil { ... } Defensive patterns
Strategy: try-catch
Type guard
func isParseResponseError(err error) bool {
return err != nil && strings.Contains(err.Error(), "qwen tts: parse response")
} Try / catch
audio, _, err := q.Synthesize(ctx, text, opts)
if isParseResponseError(err) {
slog.Error("qwen tts returned non-JSON body — check proxy/endpoint", "err", err)
return fmt.Errorf("TTS service returned an unexpected response")
} Prevention
- Log the raw response body whenever unmarshal fails.
- Ensure no corporate proxy/WAF rewrites API responses.
- Pin and periodically review the API version behind BaseURL.
- Check Content-Type of responses in integration tests.
When it happens
Trigger: json.Unmarshal(body, &result) fails: body is HTML (proxy/auth portal page), truncated JSON, gzip/content-type mismatch, or an undocumented error envelope shape.
Common situations: A captive portal or corporate proxy returning HTML with 200; an API gateway returning a JSON error with a different field layout; binary/garbage body due to missing Accept-Encoding handling; provider API version drift changing the response schema.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- qwen tts: marshal request: %w
- qwen tts API %d: %s
- qwen tts API error %s: %s
- marshal request: %w
- parse response: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ae90138d1a5564bf.
Report an issue: GitHub.