chenhg5/cc-connect · error

qwen tts: empty audio URL in response

Error message

qwen tts: empty audio URL in response

What it means

QwenTTS.Synthesize (core/tts.go:176) calls the Alibaba DashScope multimodal-generation API, parses the JSON body, and requires output.audio.url to contain a temporary URL from which the WAV file can be downloaded. This error is thrown when the API returned HTTP 200 with a parsable body and no business error code, yet the audio URL field is empty — i.e. the response shape did not carry the expected result.

Source

Thrown at core/tts.go:176

	}

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

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

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Verify the configured model is a DashScope TTS model (default qwen3-tts-flash) that returns output.audio.url for this endpoint
  2. Log the raw response body on this error to inspect what output.audio actually contained
  3. Check BaseURL points at the multimodal-generation endpoint, not another DashScope service
  4. Update the client if DashScope changed the response schema; if the API now returns base64 audio, adapt parsing to that shape

Example fix

// before
if result.Output.Audio.URL == "" {
    return nil, "", fmt.Errorf("qwen tts: empty audio URL in response")
}
// after
if result.Output.Audio.URL == "" {
    return nil, "", fmt.Errorf("qwen tts: empty audio URL in response: body=%s", string(body))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call validation possible; verify provider/model config at startup:
if ttsCfg.Provider == "qwen" && !strings.HasPrefix(ttsCfg.Model, "qwen") && ttsCfg.Model != "" {
    log.Printf("warning: model %q may not return an audio URL from the DashScope multimodal endpoint", ttsCfg.Model)
}

Type guard

func hasAudioURL(body []byte) bool {
    var r struct { Output struct { Audio struct { URL string `json:"url"` } `json:"audio"` } `json:"output"` }
    if err := json.Unmarshal(body, &r); err != nil { return false }
    return r.Output.Audio.URL != ""
}

Try / catch

audio, format, err := tts.Synthesize(ctx, text, opts)
if err != nil {
    if strings.Contains(err.Error(), "empty audio URL") {
        // fall back to a secondary TTS provider or notify user
        return fallbackSynthesize(ctx, text)
    }
    return err
}

Prevention

When it happens

Trigger: DashScope returns 200 with a JSON body whose output.audio.url is missing or empty: e.g. the configured model does not return audio URLs (wrong model name for this endpoint), the API changed its response schema, a partial success was returned, or a proxy/gateway answered 200 with a non-TTS JSON body.

Common situations: Configuring QwenTTS with a model other than a qwen-tts family model (e.g. a text-only qwen model), pointing BaseURL at a compatible-but-different endpoint that returns audio inline as base64 instead of a URL, or DashScope API schema drift.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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