Hmbown/CodeWhale · error
Compaction lifecycle task ended before acknowledgement
Error message
Compaction lifecycle task ended before acknowledgement
What it means
Raised when the oneshot acknowledgement channel for a compaction turn is dropped before the lifecycle task sends a value — the spawned compaction monitor ended (panicked, aborted, or exited) without accepting or rejecting the compaction. The RecvError is converted to this anyhow error so the caller fails fast instead of awaiting forever.
Solutions
- Retry the compaction; the store was kept consistent (turn either persisted or cleaned up).
- Check logs for a panic in the compaction lifecycle task at that time.
- Ensure the application is not shutting down the Tokio runtime while compactions are in flight.
- Report as a bug if reproducible — the lifecycle task must always send acceptance or rejection.
Defensive patterns
Strategy: retry
Try / catch
match runtime.compact_thread(&thread_id, req).await {
Err(e) if e.to_string().contains("ended before acknowledgement") => {
// lifecycle task died: check logs for panic, then retry compaction
}
r => r?,
} Prevention
- Keep the runtime alive while compactions are in flight.
- Fix lifecycle-task panics surfaced in logs.
- Avoid concurrent thread unload during compaction.
- Ensure sufficient memory for engine worker tasks.
When it happens
Trigger: Awaiting `acceptance_rx` at the end of `compact_thread` after spawning the claimed-turn monitor with `ClaimedTurnKind::Compaction`, when the sender is dropped without a message.
Common situations: Panic inside the compaction lifecycle task (check stderr/logs); Tokio runtime shutdown mid-compaction; engine teardown/abort racing the compaction submission.
Related errors
- Failed to trigger compaction: engine operation channel…
- Turn lifecycle task ended before acknowledgement
- Failed to sync thread session
- lifecycle outbox writer task is gone
- Steer settlement task ended before acknowledgement
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ea3e6c8ee3aca6dd.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:10682
current_thread.allow_shell,
current_thread.trust_mode,
policy.auto_approve(),
policy.permission,
configured_sandbox_mode,
);
engine.send_reserved_op(permit, op);
touch_lru(&mut active.lru, thread_id);
self.spawn_claimed_turn_monitor(
turn.clone(),
None,
engine.clone(),
ClaimedTurnKind::Compaction,
)
};
acceptance_rx
.await
.map_err(|_| anyhow!("Compaction lifecycle task ended before acknowledgement"))?
.map_err(anyhow::Error::msg)
}
#[cfg(test)]
pub fn events_since(
&self,
thread_id: &str,
since_seq: Option<u64>,
) -> Result<Vec<RuntimeEventRecord>> {
self.store.events_since(thread_id, since_seq)
}
pub(crate) async fn events_since_async(
&self,
thread_id: &str,
since_seq: Option<u64>,
) -> Result<Vec<RuntimeEventRecord>> {
// Startup recovery deliberately queues terminal receipts until anView on GitHub (pinned to 73e0f67d83)