chenhg5/cc-connect · error

qwen tts: parse response

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.

Solutions

  1. Log the raw body on this failure to see what was actually returned.
  2. Check whether a proxy/intermediary is rewriting the response (HTML login pages, WAF blocks).
  3. Verify the BaseURL points at the JSON API endpoint, not a console or redirect URL.
  4. 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

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/ae90138d1a5564bf. Report an issue: GitHub.

Appendix: 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)