chenhg5/cc-connect · error
qwen tts API error %s: %s
Error message
qwen tts API error %s: %s
What it means
The Qwen TTS API can return HTTP 200 with an application-level error encoded in the JSON envelope (non-empty "code" and "message"). Synthesize detects result.Code != "" and surfaces it as 'qwen tts API error <code>: <message>'. HTTP status alone is insufficient for this API.
Source
Thrown at core/tts.go:173
}
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()
wavData, err := io.ReadAll(audioResp.Body)
if err != nil {View on GitHub (pinned to 4000b2338a)
Solutions
- Read the code and message in the error and look them up in the Dashscope error-code docs.
- Fix the input per the message: shorten text, correct language_type, use an entitled model.
- Check account entitlement/quota for the chosen model in the provider console.
- Surface the code/message to the end user in the messaging layer instead of a generic failure.
Example fix
// before
code := result.Code // checked after unmarshal, surfaced only as error
// after
if result.Code != "" {
slog.Warn("qwen tts business error", "code", result.Code, "msg", result.Message)
return nil, "", fmt.Errorf("qwen tts API error %s: %s", result.Code, result.Message)
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight input checks
if len([]rune(text)) > maxQwenInputChars {
return fmt.Errorf("text too long for Qwen TTS (limit ~%d chars)", maxQwenInputChars)
}
if opts.LanguageType != "" && !supportedLanguageTypes[opts.LanguageType] {
return fmt.Errorf("unsupported language_type %q", opts.LanguageType)
} Type guard
func isQwenBusinessError(err error) (code, msg string, ok bool) {
if err == nil { return "", "", false }
const p = "qwen tts API error "
if !strings.HasPrefix(err.Error(), p) { return "", "", false }
rest := strings.TrimPrefix(err.Error(), p)
parts := strings.SplitN(rest, ": ", 2)
return parts[0], strings.Join(parts[1:], ": "), true
} Try / catch
_, _, err := q.Synthesize(ctx, text, opts)
if code, msg, ok := isQwenBusinessError(err); ok {
reply(fmt.Sprintf("TTS failed (%s): %s", code, msg))
return
} Prevention
- Validate input length and language_type against provider limits before calling.
- Surface the provider's code/message to users instead of a generic failure.
- Keep a mapping of common Qwen error codes to user actions.
- Watch for entitlement errors after changing model names.
When it happens
Trigger: A 200 response whose JSON contains a non-empty top-level "code" field — e.g. invalid parameter values, model not entitled, text too long, content policy rejection.
Common situations: Input text exceeding the model's length limit; unsupported language_type value; model name unavailable to the account; content filtered by the provider despite successful HTTP handling.
Related errors
- qwen tts API %d: %s
- qwen tts: parse response: %w
- qwen tts: marshal request: %w
- qwen tts: create request: %w
- qwen tts: request: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/7df0c14a65ad9a08.
Report an issue: GitHub.