deepset-ai/haystack · error
The Chat Generator returned no usable text to use as a conve
Error message
The Chat Generator returned no usable text to use as a conversation summary. Generator output: {result}. What it means
_apply_summary raises RuntimeError when the summarization ChatGenerator's result contains no usable text (haystack/hooks/compaction/summarization.py:440). The hook inspects result['replies'] and needs a non-empty, non-whitespace reply to insert as the conversation summary; without it, compaction cannot proceed so it fails loudly rather than corrupting the conversation.
Source
Thrown at haystack/hooks/compaction/summarization.py:440
before_tokens: int,
token_counter: TokenCounter,
) -> tuple[list[ChatMessage], int]:
"""
Swap the selected messages for the generated summary.
:param messages: The conversation to compact, ordered oldest to newest.
:param indices: The positions of the messages to replace with a summary.
:param result: The Chat Generator's output, which should contain one usable summary.
:param before_tokens: The already measured size of `messages`.
:param token_counter: The counter used to verify that the summary actually shrinks the conversation.
:returns: The conversation with the selected messages replaced by the summary, and its measured token count.
:raises RuntimeError: If the generator returned no usable text, or if the swap did not make the conversation
smaller, in which case keeping the raw messages is the better outcome.
"""
replies = result.get("replies") or []
text = replies[-1].text if replies else None
if not text or not text.strip():
raise RuntimeError(
"The Chat Generator returned no usable text to use as a conversation summary. "
f"Generator output: {result}."
)
summary = ChatMessage.from_user(
text=f"<conversation_summary>\n{text.strip()}\n</conversation_summary>",
meta={_COMPACTION_META_KEY: {"strategy": _STRATEGY, "summarized_messages": len(indices)}},
)
compacted = _replace_indices(messages=messages, indices=indices, summary=summary)
after_tokens = token_counter.count(messages=compacted)
if after_tokens >= before_tokens:
raise RuntimeError(
f"The generated summary did not reduce the conversation size ({before_tokens} tokens before and "
f"{after_tokens} tokens after)."
)
return compacted, after_tokens
def _report_failure(self, error: Exception) -> None:View on GitHub (pinned to e318778c9b)
Solutions
- Inspect the logged result dict to see why replies were empty.
- Increase max_tokens / adjust the summary_instruction so the model reliably returns plain text.
- Check the generator's API/key configuration — auth or quota failures often surface as empty replies.
- Wrap compact() in error handling so a failed summary leaves the conversation intact and can be retried.
Example fix
// before
gen = OpenAIChatGenerator(model="gpt-4o-mini", generation_kwargs={"max_tokens": 1})
// after
gen = OpenAIChatGenerator(model="gpt-4o-mini", generation_kwargs={"max_tokens": 1024}) Defensive patterns
Strategy: try-catch
Validate before calling
def summary_will_be_usable(gen) -> bool:
# smoke-test the generator returns text replies before wiring it into the compactor
result = gen.run([ChatMessage.from_user("Reply with 'ok'.")])
replies = result.get("replies") or []
return bool(replies and replies[-1].text and replies[-1].text.strip()) Type guard
def has_usable_reply(result: dict) -> bool:
replies = result.get("replies") or []
return bool(replies) and bool((replies[-1].text or "").strip()) Try / catch
try:
compacted = compactor.compact(messages, target_tokens, counter)
except RuntimeError as e:
if "no usable text" in str(e):
logger.warning("summarizer returned empty output; keeping raw messages")
compacted = messages # fallback
else:
raise Prevention
- Set adequate max_tokens on the summarization generator
- Test the generator's replies format once at startup
- Handle model refusals by rephrasing summary_instruction
- Check API key/quota health — failures often surface as empty replies
When it happens
Trigger: The generator returns an empty replies list, replies with empty/whitespace-only text, or an unexpected result dict — e.g. the model refused, returned a tool call instead of text, or the generator errored into a non-text result.
Common situations: LLM refusal or safety stop producing empty output; misconfigured generator whose prompt yields a tool call; generator returning an error dict after an API failure; very small max_tokens truncating the reply to empty.
Related errors
- The generated summary did not reduce the conversation size (
- Failed to perform conversion between components:\nSender com
- `context_window` must be a positive number of tokens, got {c
- `compact_at` and `compact_to` must satisfy 0 < compact_to <
- `min_keep_steps` must be at least 0, got {min_keep_steps}.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/9f0a264d9c241395.
Report an issue: GitHub.