chenhg5/cc-connect · error
qwen asr API %d: %s
Error message
qwen asr API %d: %s
What it means
Thrown by QwenSTT.Transcribe in core/speech.go when the Qwen ASR HTTP endpoint returns a non-200 status. The error embeds the status code and the raw response body so the caller can see the upstream API's reason (auth failure, bad model, oversized payload, etc.). It wraps a server-side rejection, not a local bug.
Source
Thrown at core/speech.go:183
if err != nil {
return "", fmt.Errorf("create request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+q.APIKey)
req.Header.Set("Content-Type", "application/json")
resp, err := q.Client.Do(req)
if err != nil {
return "", fmt.Errorf("qwen asr request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("read response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("qwen asr API %d: %s", resp.StatusCode, string(body))
}
var result struct {
Choices []struct {
Message struct {
Content string `json:"content"`
} `json:"message"`
} `json:"choices"`
}
if err := json.Unmarshal(body, &result); err != nil {
return "", fmt.Errorf("parse response: %w", err)
}
if len(result.Choices) == 0 {
return "", fmt.Errorf("qwen asr: empty choices in response")
}
return strings.TrimSpace(result.Choices[0].Message.Content), nil
}View on GitHub (pinned to 4000b2338a)
Solutions
- Read the status code and body in the error message to identify the upstream cause (401/403 -> fix API key; 404 -> fix BaseURL/model name; 429 -> back off; 5xx -> retry later).
- Verify speech provider API key and BaseURL in config.toml against Qwen/DashScope docs.
- Confirm the configured model name is a valid Qwen audio model.
- Check audio file size/duration against Qwen limits and convert to a supported format (see ConvertAudioToMP3).
- For 429/5xx, retry with exponential backoff.
Example fix
// before: fails with opaque 401 baseURL = "https://dashscope.aliyuncs.com/api/v1" // wrong path // after baseURL = "https://dashscope.aliyuncs.com/compatible-mode/v1" // correct OpenAI-compatible path, valid API key
Defensive patterns
Strategy: try-catch
Validate before calling
if cfg.QwenAPIKey == "" { return errors.New("qwen: missing API key") }
if !strings.HasPrefix(cfg.QwenBaseURL, "https://") { return errors.New("qwen: invalid BaseURL") } Try / catch
text, err := stt.Transcribe(ctx, audio)
if err != nil {
if strings.Contains(err.Error(), "qwen asr API") {
// non-200: log status, surface friendly 'speech service unavailable' to user
slog.Warn("qwen asr upstream error", "err", err)
return "", ErrSpeechServiceUnavailable
}
return err
} Prevention
- Validate provider API keys at startup with a doctor/health check.
- Pin and review BaseURL/model names against current provider docs.
- Convert audio to mp3 and enforce size limits before calling Transcribe.
- Add retry-with-backoff for 429/5xx status codes.
When it happens
Trigger: Calling Transcribe with a Qwen provider when the POST to the Qwen chat-completions-style ASR endpoint responds with any status other than 200 — e.g. 401 invalid API key, 404 wrong model name or BaseURL path, 413 audio too large, 429 rate limit, 5xx Qwen outage.
Common situations: Expired or wrong DASHSCOPE/Qwen API key in config.toml; BaseURL pointing at the wrong region or missing /compatible-mode/v1; model name typo (e.g. qwen-audio-asr vs qwen2-audio); sending an audio file exceeding the API size limit; transient Qwen service errors.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- gemini stt API %d: %s
- qwen asr request: %w
- gemini stt: request: %w
- qwen tts: request: %w
- qwen tts: download audio: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/eed7dac6d6aceae0.
Report an issue: GitHub.