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

  1. 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).
  2. Verify speech provider API key and BaseURL in config.toml against Qwen/DashScope docs.
  3. Confirm the configured model name is a valid Qwen audio model.
  4. Check audio file size/duration against Qwen limits and convert to a supported format (see ConvertAudioToMP3).
  5. 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

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


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