chenhg5/cc-connect · warning
qwen asr: empty choices in response
Error message
qwen asr: empty choices in response
What it means
Thrown by QwenSTT.Transcribe in core/speech.go when the Qwen ASR response parses as valid JSON but the 'choices' array is empty. The API accepted the request and returned 200 with well-formed JSON, yet produced no transcription candidate.
Source
Thrown at core/speech.go:197
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
}
// GeminiSTT implements SpeechToText using the Google Gemini API.
// Audio is sent as inline_data (base64) in the contents array against the
// generateContent endpoint; the API key is sent via the x-goog-api-key header.
type GeminiSTT struct {
APIKey string
Model string
BaseURL string // internal; defaults to Google API, overridable for testing
Client *http.Client
}
func NewGeminiSTT(apiKey, model string) *GeminiSTT {
if model == "" {
model = "gemini-flash-latest"View on GitHub (pinned to 4000b2338a)
Solutions
- Check the audio file is non-empty and contains actual speech.
- Convert the audio to a widely supported format (mp3/wav) via ConvertAudioToMP3 before sending.
- Return a user-friendly 'no speech detected' message instead of treating it as a system failure.
- Try a different Qwen audio model if the current one consistently yields empty choices.
- Inspect the full response body (log it) for any finish_reason or filtering metadata.
Defensive patterns
Strategy: fallback
Validate before calling
info, err := os.Stat(audioPath)
if err != nil || info.Size() < 1024 { return errors.New("audio file too small or missing") } Try / catch
text, err := stt.Transcribe(ctx, audio)
if err != nil {
if strings.Contains(err.Error(), "empty choices") {
return "", ErrNoSpeechDetected // treat as 'no speech', not a crash
}
return err
} Prevention
- Pre-check audio is non-empty and contains speech (energy/VAD check if possible).
- Always convert to a supported format (mp3/wav) before upload.
- Treat empty results as user-facing 'no speech detected' instead of a system error.
- Log full response bodies to spot filtering metadata.
When it happens
Trigger: Qwen returns HTTP 200 with choices:[] — typically when the audio contained no recognizable speech, the audio format was unsupported/mostly silence, or the model refused/filtered the content.
Common situations: User sends a voice message that is pure noise or silence; audio codec Qwen can't decode properly; content filter triggered; a model update changed behavior for edge-case inputs.
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
- gemini stt: empty response
- qwen asr API %d: %s
- parse response: %w
- codex app-server turn/start returned empty turn id
- incomplete onboarding response
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/8aaa16fdbaddd11f.
Report an issue: GitHub.