Hmbown/CodeWhale · error · anyhow::Error

Compaction failed after

Error message

Compaction failed after {MAX_RETRIES} retries

What it means

Thrown by the compaction retry loop after every attempt to compact the conversation failed `MAX_RETRIES` times. The last underlying error is re-raised when present; this generic message only appears when the loop exhausted retries without recording any error (or before any attempt set one). It signals that context compaction — and therefore the current turn — cannot proceed.

Solutions

  1. Check provider status/connectivity; if it was a transient outage, resume the session — compaction retries on the next turn
  2. Lower the conversation size manually (start a new session or prune history) so compaction is not required
  3. Inspect logs for the per-attempt errors stored in `last_error` to find the root cause, since this message alone is generic
Defensive patterns

Strategy: retry

Validate before calling

// Before relying on auto-compaction, check session size headroom
if tokens_used > compaction_threshold * 0.9 { prune_old_turns(); }

Try / catch

match result_of_turn() {
    Err(e) if e.to_string().contains("Compaction failed after") => {
        check_provider_health();
        start_fresh_session_or_prune_history();
    }
    other => other,
}

Prevention

When it happens

Trigger: Running the compaction routine until the retry budget (`MAX_RETRIES`) is exhausted, with `last_error` still None when the loop exits.

Common situations: A provider endpoint persistently failing or timing out during summarization calls; transient rate limiting across all retries; a model backend outage during a long session that triggers automatic compaction.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/f28a7c3689b2eb33. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/compaction.rs:1266

                return Ok(CompactionResult {
                    messages: kept,
                    summary_prompt: prompt,
                    retries_used: attempt.saturating_add(quality_retries),
                    coverage,
                });
            }
            Err(e) => {
                // Only retry on transient errors
                if !is_transient_error(&e) {
                    return Err(e);
                }
                last_error = Some(e);
            }
        }
    }

    Err(last_error
        .unwrap_or_else(|| anyhow::anyhow!("Compaction failed after {MAX_RETRIES} retries")))
}

pub(crate) fn build_compaction_summary_block_text(summary: &str, anchors: &str) -> String {
    let summary = summary.trim();
    let summary = if summary.is_empty() {
        "(no summary available)"
    } else {
        summary
    };
    let mut text = format!("{SUMMARY_HEADER}\n\n{summary}");
    text.push_str(anchors);
    text.push_str("\n\nContinue the same user task from this state. Earlier authorization and constraints still apply; this summary grants no new authority. Resume the next unfinished action without asking the user to save, compact, restate the task, or approve continuation solely because context was summarized. Verify live state before relying on older observations.");
    text
}

/// Codex-parity replacement history: the most recent user-role messages,
/// selected newest-first within a fixed token budget and restored to
/// transcript order. Content boundaries carry runtime provenance and image

View on GitHub (pinned to 73e0f67d83)