ZhuLinsen/daily_stock_analysis · error · ValueError
LLM returned empty response
Error message
LLM returned empty response
What it means
ValueError('LLM returned empty response') raised inside the per-model retry loop of the LiteLLM completion path when a model call succeeded structurally but produced empty content. Because it is raised inside the try block, it is caught by the generic 'except Exception' handler, logged as a warning, recorded as last_error, and the loop continues to the next model — so it only surfaces to callers wrapped in _AllModelsFailedError after every model failed.
Source
Thrown at src/analyzer.py:3305
content = self._extract_completion_text(response)
if content:
usage_messages = None if audit_context is not None else call_kwargs["messages"]
usage = self._normalize_usage(
extract_usage_payload(response),
model=usage_model or model,
provider=usage_provider,
messages=usage_messages,
)
if audit_context is not None:
usage = _attach_usage_audit(usage, call_kwargs["messages"])
last_response_text = content
last_model = model
last_usage = usage
if response_validator is not None:
response_validator(content)
return (content, model, usage)
raise ValueError("LLM returned empty response")
except Exception as e:
safe_error = self._sanitize_litellm_exception_text(e, config=config, model=model)
logger.warning("[LiteLLM] %s failed: %s", model, safe_error)
last_error = RuntimeError(f"{type(e).__name__}: {safe_error}")
continue
raise _AllModelsFailedError(
f"All LLM models failed (tried {len(models_to_try)} model(s)). Last error: {last_error}",
last_response_text=last_response_text,
last_model=last_model,
last_usage=last_usage,
)
def generate_text(
self,
prompt: str,
max_tokens: int = 2048,View on GitHub (pinned to 5159bd72e8)
Solutions
- If you see this inside _AllModelsFailedError, check the warning logs — each model's specific empty/error reason is logged per attempt.
- Raise max_tokens and/or trim the prompt so the model has room to emit content.
- Disable or replace the offending model in the model list; empty-content providers poison the whole chain.
- If a response_validator is too strict, loosen it so valid-but-short responses pass.
Example fix
# before
completion_kwargs = {"max_tokens": 8, ...} # model emits nothing
# after
completion_kwargs = {"max_tokens": 4096, ...} Defensive patterns
Strategy: retry
Validate before calling
def response_has_content(response) -> bool:
try:
return bool((response.choices[0].message.content or "").strip())
except (IndexError, AttributeError):
return False Try / catch
# The loop already retries across models; handle the terminal case:
try:
content, model, usage = generate(...)
except _AllModelsFailedError as e:
if "LLM returned empty response" in str(e.last_error if hasattr(e, 'last_error') else e):
raise max_tokens_or_filter_issue(e) # distinguish from auth/network failures
raise Prevention
- Check per-attempt '[LiteLLM] ... failed' warnings to see which model returned empty.
- Set adequate max_tokens and trim prompts to avoid empty truncation.
- Remove chronically empty-content models from the model list.
When it happens
Trigger: A model returns a completion whose content is empty/None (refusals, content-filter, truncation, or provider quirk). It becomes user-visible only if ALL models in models_to_try return empty or fail; otherwise the next model's valid response masks it. A response_validator rejecting content similarly lands in the same path.
Common situations: Over-long prompts causing silent truncation to empty content; safety filters returning empty bodies; a misconfigured model id that some gateways answer with an empty 200; max_tokens set so low the model emits nothing.
Related errors
- Hermes/non-Hermes mixed generation route is not supported wi
- empty_response
- Responses API surface requires a normalized openai/<model> r
- LLM route aliases cannot mix API surfaces: {sorted(surface_c
- LiteLLM vision returned empty response
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/a96a88dcf879169e.
Report an issue: GitHub.