Hmbown/CodeWhale · error

Compaction summary response was unusable: a placeholder was

Error message

Compaction summary response was unusable: a placeholder was returned.

What it means

The normalized summary matched a known placeholder or refusal string ('no summary available', 'n/a', 'i cannot provide a summary', ...) at crates/tui/src/compaction.rs:1153, so it is treated as unusable rather than persisted as the session checkpoint.

Source

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

        .to_ascii_lowercase();
    if normalized.is_empty() {
        anyhow::bail!(
            "Compaction summary response was unusable: only whitespace or punctuation was returned."
        );
    }
    if matches!(
        normalized.as_str(),
        "no summary available"
            | "summary unavailable"
            | "no summary"
            | "n/a"
            | "na"
            | "not available"
            | "i cannot provide a summary"
            | "i can't provide a summary"
            | "unable to provide a summary"
    ) {
        anyhow::bail!("Compaction summary response was unusable: a placeholder was returned.");
    }
    Ok(())
}

/// Drop the oldest history message before retrying an over-window summary
/// request (Codex parity: `history.remove_first_item()`), plus any tool
/// results the removal orphans — strict providers reject unpaired results.
fn drop_oldest_history_messages(messages: &mut Vec<Message>) {
    if messages.len() <= 1 {
        return;
    }
    messages.remove(0);
    while messages.len() > 1
        && messages[0]
            .content
            .iter()
            .any(|block| matches!(block, ContentBlock::ToolResult { .. }))
    {

View on GitHub (pinned to 8880682c63)

Solutions

  1. Retry - refusals are often stochastic
  2. Switch or adjust the compaction model (one less prone to refusals)
  3. If content in the session triggers refusals, compact earlier so the offending context is smaller
  4. Check whether an intermediary cache is returning a canned response
Defensive patterns

Strategy: fallback

Validate before calling

// Reject known placeholder texts before accepting a summary
const PLACEHOLDERS: [&str; 8] = ["no summary available","summary unavailable","no summary","n/a","na","not available","i cannot provide a summary","i can't provide a summary"];
fn is_placeholder(s: &str) -> bool { PLACEHOLDERS.contains(&s.trim().to_ascii_lowercase().as_str()) }

Type guard

fn is_placeholder_summary_error(msg: &str) -> bool {
    msg.contains("a placeholder was returned")
}

Try / catch

// Fall back to a second model; refusals follow the model, not the input
match compact().await {
    Err(e) if is_placeholder_summary_error(&e.to_string()) => compact_with_model(alt_model).await,
    r => r,
}

Prevention

When it happens

Trigger: The summary model refuses the request, a safety filter deflects it, or a gateway returns templated fallback text that happens to match the placeholder list.

Common situations: Refusals triggered by sensitive session content; models that answer literally when they cannot comply; identical canned responses from caching layers.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/aee4326a6a60dab6. Report an issue: GitHub.