Hmbown/CodeWhale · warning
Runtime terminal receipt monitor failed
Error message
Runtime terminal receipt monitor failed: {error} What it means
During RuntimeThreadManager shutdown, terminal receipt monitors are awaited with await_retained_completion. If any turn monitor resolves with an error, shutdown records 'Runtime terminal receipt monitor failed'. Receipt monitors are background tasks that publish terminal receipts when a turn finishes, so this indicates a monitor task ended abnormally.
Solutions
- Check the wrapped {error} to identify which monitor failed and why
- Ensure turn completion paths publish their receipts successfully before shutdown
- Verify the turn store is accessible so receipt writes succeed
- Call shutdown again or drain remaining monitors if the loop broke out with monitors still present
Example fix
// before
let _ = manager.shutdown().await;
// after
match manager.shutdown().await {
Ok(()) => {}
Err(e) if e.to_string().contains("receipt monitor") => {
tracing::warn!("receipt monitor failed during shutdown: {e:#}");
}
Err(e) => return Err(e),
} Defensive patterns
Strategy: try-catch
Validate before calling
let monitors = manager.turn_monitors.lock().clone(); let monitors_done = monitors.iter().all(completion_finished);
Type guard
fn monitor_finished(monitor: &RuntimeCompletion) -> bool { completion_finished(monitor) } Try / catch
match manager.shutdown().await {
Err(e) if e.to_string().contains("receipt monitor") => {
tracing::warn!("monitor failure at shutdown (turn receipts may be missing): {e:#}");
}
other => other?,
} Prevention
- Let receipt monitors finish (turns reach terminal status) before shutdown
- Ensure receipt writes to the store cannot fail silently
- Reconcile missing receipts after shutdown if monitors failed
When it happens
Trigger: Calling RuntimeThreadManager::shutdown while turn monitors are registered; a monitor's retained completion returns Err (monitor task failed or was cancelled), and the retain loop that drops finished monitors then finds remaining failures.
Common situations: Tearing down the runtime with turns whose receipt monitors never completed; a monitor task panicking while persisting a receipt; store write failures during receipt publication.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- engine event channel closed before turn
- Runtime engine shutdown failed
- Runtime turn interruption failed
- Task worker shutdown failed
- Wait for the pet recorder write before closing.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/d85e8560a588af1e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:5230
{
let _ = engine.send(Op::Shutdown).await;
}
for (_, worker) in workers {
if let Err(error) = await_retained_completion(&worker).await {
failure = Some(anyhow!("Runtime engine shutdown failed: {error}"));
}
}
// Recovery reads can publish receipts too. Flushes that already passed
// their admission check retain this mutex through all receipt writes;
// later readers see the closed latch under the same mutex.
{
let _recovery = self.recovery_flush.lock().await;
}
loop {
let monitors = self.turn_monitors.lock().clone();
for monitor in monitors {
if let Err(error) = await_retained_completion(&monitor).await {
failure = Some(anyhow!("Runtime terminal receipt monitor failed: {error}"));
}
}
let mut monitors = self.turn_monitors.lock();
monitors.retain(|monitor| !completion_finished(monitor));
if monitors.is_empty() {
break;
}
}
self.engine_workers
.lock()
.retain(|(_, worker)| !completion_finished(worker));
let mut active = self.active.lock().await;
active.engines.clear();
active.lru.clear();
failure.map_or(Ok(()), Err)
}
fn track_receipt_worker(&self, worker: tokio::task::JoinHandle<()>) {View on GitHub (pinned to 73e0f67d83)