harry0703/MoneyPrinterTurbo · error · ValueError

[qwen] returned empty choices

Error message

[qwen] returned empty choices

What it means

Qwen-specific guard in _extract_qwen_generation_text: the DashScope Generation response's output.choices exists as a key but is an empty list (a warning is logged before raising). Distinguished from output.text fallback: an explicitly empty choices list means the chat-form response carries no completions, so falling through to output.text would mask the failure.

Source

Thrown at app/services/llm.py:128

    except (KeyError, TypeError, AttributeError):
        return getattr(value, key, None)


def _extract_qwen_generation_text(response) -> str:
    """
    从 DashScope Generation 响应中提取文本。

    Qwen 使用 `messages` 调用时返回的是 chat 结构:
    `output.choices[0].message.content`;旧 completion 形态才会返回
    `output.text`。这里两个路径都兼容,避免 `output.text` 为 None 时
    继续 `.replace()` 触发不可诊断的 AttributeError。
    """
    output = _get_response_field(response, "output")
    choices = _get_response_field(output, "choices") if output else None
    if choices is not None:
        if not choices:
            logger.warning("Qwen returned an empty choices list")
            raise ValueError("[qwen] returned empty choices")

        first_choice = choices[0]
        message = _get_response_field(first_choice, "message")
        content = _get_response_field(message, "content") if message else None
        if content is not None:
            return _normalize_text_response(content, "qwen")

    text = _get_response_field(output, "text") if output else None
    return _normalize_text_response(text, "qwen")


def _generate_response(prompt: str, app_config=None) -> str:
    try:
        # WebUI 在视频生成期间允许用户准备下一条文案。调用方可以传入提交瞬间
        # 的配置快照,确保模型请求重试期间不会因为后台任务结束并应用新配置,
        # 而切换到另一个 Provider、Base URL 或模型。
        runtime_app_config = app_config if app_config is not None else config.app
        llm_provider = str(

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Log the full response including status_code and code/message fields — DashScope embeds the real reason there (e.g. DataInspectionFailed)
  2. Adjust the prompt to avoid content-policy triggers
  3. Verify the model name resolves (a wrong model often yields degenerate output instead of a clear error)
  4. Retry once with backoff for rate-limit-related empty responses

Example fix

# before
response = dashscope.Generation.call(model=model_name, messages=[...])
# silently empty output -> downstream None errors

# after
response = dashscope.Generation.call(model=model_name, messages=[...])
if response.status_code != "200":
    raise RuntimeError(f"dashscope error: {response.code} {response.message}")
text = _extract_qwen_generation_text(response, "qwen")
Defensive patterns

Strategy: try-catch

Validate before calling

if response is None or response.output is None:
    raise ValueError("dashscope returned no output")
if getattr(response, "status_code", 200) != 200:
    raise ValueError(f"dashscope error: {getattr(response, 'code', '')} {getattr(response, 'message', '')}")

Type guard

def qwen_has_chat_output(response) -> bool:
    output = getattr(response, "output", None) or {}
    choices = output.get("choices", None) if isinstance(output, dict) else None
    if choices is not None:
        return bool(choices) and bool((choices[0].get("message") or {}).get("content"))
    return bool(output.get("text"))

Try / catch

try:
    text = _extract_qwen_generation_text(response, "qwen")
except ValueError as e:
    if "empty choices" in str(e):
        raise ValueError(f"qwen blocked request: code={getattr(response, 'code', '?')}")

Prevention

When it happens

Trigger: dashscope.Generation.call with messages returns output={'choices': []} — DashScope does this on content-policy blocks or certain error codes that still produce a response object.

Common situations: Chinese-content policy interception silently emptying choices, DashScope API version drift, invalid model names that yield an empty chat response instead of an error status, or rate-limit soft failures.

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/5effa318e0045592. Report an issue: GitHub.