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
- Log the full response including status_code and code/message fields — DashScope embeds the real reason there (e.g. DataInspectionFailed)
- Adjust the prompt to avoid content-policy triggers
- Verify the model name resolves (a wrong model often yields degenerate output instead of a clear error)
- 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
- Always inspect DashScope status_code/code/message before parsing output
- Keep prompts clear of content-policy triggers for Chinese providers
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
- [{llm_provider}] returned an error response: "{response}"
- [{llm_provider}] returned an invalid response: "{response}"
- [{llm_provider}] returned an empty response
- [{llm_provider}] returned empty text content
- [{llm_provider}] returned non-text content: {type(content)._
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/5effa318e0045592.
Report an issue: GitHub.