jamiepine/voicebox · error · HTTPException
LLM produced empty output; nothing to speak.
Error message
LLM produced empty output; nothing to speak.
What it means
Returned as HTTP 500 by POST /generate. After a successful personality rewrite, the route strips the result text and checks `if not text`. If the LLM returned only whitespace or an empty string, there is nothing to send to TTS, so it raises this 500. It is a server-side quality gate: the LLM produced no usable content.
Source
Thrown at backend/routes/generations.py:88
engine = _resolve_generation_engine(data, profile)
try:
profiles.validate_profile_engine(profile, engine)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
model_size = (data.model_size or "1.7B") if engine_has_model_sizes(engine) else None
text = data.text
source = "manual"
if data.personality and getattr(profile, "personality", None):
try:
llm_result = await personality.rewrite_as_profile(profile.personality, data.text)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
text = llm_result.text.strip()
if not text:
raise HTTPException(status_code=500, detail="LLM produced empty output; nothing to speak.")
source = "personality_speak"
generation = await history.create_generation(
profile_id=data.profile_id,
text=text,
language=data.language,
audio_path="",
duration=0,
seed=data.seed,
db=db,
instruct=data.instruct,
generation_id=generation_id,
status="generating",
engine=engine,
model_size=model_size if engine_has_model_sizes(engine) else None,
source=source,
)
View on GitHub (pinned to 51f49dea19)
Solutions
- Retry the request — transient empty output from the LLM often clears on retry.
- Inspect the personality prompt and relax constraints that may force empty/refusal output.
- Temporarily disable personality (personality=false) to send the original text to TTS.
- If persistent, capture the raw LLM response in the personality service logs to diagnose the empty completion.
Example fix
// before: single attempt, surface 500 to user
const r = await post('/generate', { profile_id, text, personality: true });
// after: retry once, then fall back to raw text
try {
await post('/generate', { profile_id, text, personality: true });
} catch (e) {
if (e.status === 500) await post('/generate', { profile_id, text, personality: false });
} Defensive patterns
Strategy: retry
Validate before calling
# Pre-flight: confirm the personality rewrite produces non-empty text.
result = await personality.rewrite_as_profile(profile.personality, data.text)
if not (result.text or '').strip():
# would 500 — retry once, then fall back to raw text
data.personality = False Type guard
def rewrite_is_usable(text: str) -> bool:
return bool(text and text.strip()) Try / catch
try:
client.post('/generate', json=payload)
except HTTPStatusError as e:
if e.response.status_code == 500 and 'empty output' in e.response.json().get('detail', ''):
# retry once, then fall back to raw text without personality
try:
client.post('/generate', json=payload)
except HTTPStatusError:
payload['personality'] = False
client.post('/generate', json=payload)
return
raise Prevention
- Retry once — transient empty LLM output often clears.
- Relax personality prompts that over-constrain the model into silence.
- Capture raw LLM responses in logs to diagnose persistent empties.
- Offer a personality toggle so users can fall back to raw text.
When it happens
Trigger: Personality rewrite returns an empty string; the LLM returns only whitespace/punctuation that strips to empty; a model misconfiguration causes the rewrite to yield blank output; prompt injection causes the model to refuse with an empty response.
Common situations: LLM provider returning empty completions under load or quota pressure; a personality prompt that over-constrains the model into silence; upstream model returning a refusal that the adapter reduces to empty; whitespace-only output from a misconfigured streaming adapter.
Related errors
- Profile not found
- {e}
- Generation not found
- Only failed generations can be retried
- Generation must be completed to regenerate
AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12).
Data as JSON: /api/errors/03281548e5824ee9.
Report an issue: GitHub.