chenhg5/cc-connect · error

qwen tts: download audio: %w

Error message

qwen tts: download audio: %w

What it means

QwenTTS.Synthesize downloads the synthesized WAV from the temporary URL returned by DashScope (core/tts.go:186) using the shared q.Client. This error wraps a Client.Do failure: the GET request to the audio URL could not be completed at the transport level.

Source

Thrown at core/tts.go:186

	}
	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()

	wavData, err := io.ReadAll(audioResp.Body)
	if err != nil {
		return nil, "", fmt.Errorf("qwen tts: read audio: %w", err)
	}
	return wavData, "wav", nil
}

// ──────────────────────────────────────────────────────────────
// OpenAITTS — OpenAI-compatible TTS implementation (P1)
// ──────────────────────────────────────────────────────────────

// OpenAITTS implements TextToSpeech using the OpenAI /v1/audio/speech API.
type OpenAITTS struct {
	APIKey  string
	BaseURL string

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check network egress/DNS from the machine running the code to the audio host domain
  2. Retry Synthesize — temporary URLs are short-lived, so download immediately after generation
  3. Increase the http.Client timeout in NewQwenTTS for long/large audio downloads
  4. Verify proxy/firewall rules allow HTTPS to DashScope audio/CDN domains

Example fix

// before
client = &http.Client{Timeout: 60 * time.Second}
// after
client = &http.Client{Timeout: 120 * time.Second} // tolerate slow CDN downloads
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check egress reachability at startup:
req, _ := http.NewRequest(http.MethodHead, strings.TrimRight(tts.BaseURL, "/"), nil)
if _, err := http.DefaultClient.Do(req); err != nil {
    log.Printf("warning: no network egress to TTS provider host: %v", err)
}

Try / catch

var audio []byte
var format string
var err error
for i := 0; i < 3; i++ {
    audio, format, err = tts.Synthesize(ctx, text, opts)
    if err == nil || !strings.Contains(err.Error(), "download audio") { break }
    time.Sleep(time.Duration(1<<i) * time.Second) // exponential backoff
}
if err != nil { return err }

Prevention

When it happens

Trigger: Network failure, DNS resolution failure for the audio host, TLS handshake error, the temporary URL already expired and the connection was reset, or the 60s client timeout elapsing before the download starts.

Common situations: Synthesis succeeded but the download ran from a network without internet egress (e.g. server-side code in a restricted VPC), DashScope's temporary CDN URL expired because of a delay between generation and download, or a proxy/firewall blocks the audio host (aliyuncs OSS domains).

Related errors


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