zed-industries/zed · error
Compaction produced an empty summary
Error message
Compaction produced an empty summary
What it means
After a compaction stream finishes, the accumulated summary is trimmed; if the result is empty, the compaction task returns this error instead of replacing the thread history with an empty summary. It protects the transcript from data loss when the model produced no usable summary text.
Source
Thrown at crates/agent/src/thread.rs:3210
| LanguageModelCompletionEvent::Thinking { .. }
| LanguageModelCompletionEvent::RedactedThinking { .. }
| LanguageModelCompletionEvent::ReasoningDetails(_)
| LanguageModelCompletionEvent::ToolUse(_)
| LanguageModelCompletionEvent::ToolUseJsonParseError { .. }
| LanguageModelCompletionEvent::StartMessage { .. }
| LanguageModelCompletionEvent::Compaction(_) => {}
}
}
if *cancellation_rx.borrow() {
log::debug!("Compaction cancelled after summarizing");
return Ok(ControlFlow::Break(()));
}
let summary = summary.trim().to_string();
if summary.is_empty() {
log::warn!("Compaction produced an empty summary");
return Err(anyhow::anyhow!("Compaction produced an empty summary"));
}
log::debug!("Compaction succeeded:\n{summary}");
event_stream.update_context_compaction_status(
compaction_id,
acp_thread::ContextCompactionStatus::Completed,
);
this.update(cx, |this, cx| {
let compaction = Arc::new(Message::Compaction(CompactionInfo::Summary(summary.into())));
match insertion {
CompactionInsertion::Auto { insertion_ix } => {
if insertion_ix <= this.messages.len() {
this.messages.insert(insertion_ix, compaction);
} else {
this.messages.push(compaction);
}
}View on GitHub (pinned to bc538def45)
Solutions
- Retry the compaction; transient empty outputs usually do not repeat
- Switch to a stronger or different compaction model in settings
- Check provider status and network stability if empty summaries recur
- If it recurs on one thread, reduce context pressure (manually trim older messages) before compacting again
Example fix
// before
let events = thread.update(cx, |t, cx| t.compact(id, cx))?;
consume(events).await?;
// after: retry once on empty-summary failures
for attempt in 0..2 {
let events = thread.update(cx, |t, cx| t.compact(id, cx))?;
match consume(events).await {
Ok(()) => break,
Err(err) if err.to_string().contains("empty summary") && attempt == 0 => continue,
Err(err) => return Err(err),
}
} Defensive patterns
Strategy: retry
Try / catch
for attempt in 0..2 {
match compact_thread(thread, id).await {
Ok(()) => break,
Err(err) if err.to_string().contains("empty summary") && attempt + 1 < 2 => {
continue; // transient empty output: retry compaction once
}
Err(err) => return Err(err),
}
} Prevention
- Prefer a stable, capable compaction model over weak or experimental ones
- Avoid compacting during known provider incidents or unstable networks
- Treat 'empty summary' as retryable, not as corruption of the thread
- Keep manual trim available as a fallback when compaction repeatedly fails
When it happens
Trigger: The compaction model streams only whitespace or no text at all; the summary content arrived only in event variants the accumulator ignores; or the stream glitched and completed without emitting summary content while the cancellation flag was not set.
Common situations: A weak or misbehaving compaction model returning empty output; a provider outage mid-stream yielding a completed-but-empty response; rare cancellation races where the check at the top passed but no content was ever accumulated.
Related errors
- no language model configured
- output token limit reached
- message not found
- not supported
- no thread found with ID: {id:?}
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/ac32d939fe9beb94.
Report an issue: GitHub.