Hmbown/CodeWhale · error · anyhow::Error
{error}
Error message
{error} What it means
await_dynamic_tool_settlement received Err(String) from the settlement task: the durable append of the terminal event failed (error forwarded with .to_string() at runtime_threads.rs:4264), the settlement task panicked ('Dynamic tool settlement task panicked: ...'), or it lost its claim/outcome. The registry was already reconciled: retry-safe append failures restore the call to Awaiting; failed rollbacks mark it indeterminate.
Source
Thrown at crates/tui/src/runtime_threads.rs:4327
manager.restore_dynamic_tool_claim(claim);
}
Err(format!(
"Dynamic tool settlement task panicked: {}",
panic_payload_message(&*payload)
))
}
};
let _ = ack_tx.send(result);
});
ack_rx
}
async fn await_dynamic_tool_settlement(
ack: oneshot::Receiver<std::result::Result<DynamicToolSettlementAck, String>>,
) -> Result<DynamicToolSettlementAck> {
match ack.await {
Ok(Ok(ack)) => Ok(ack),
Ok(Err(error)) => bail!("{error}"),
Err(_) => bail!("Dynamic tool settlement task ended before acknowledgement"),
}
}
async fn settle_dynamic_tool_timeout(
&self,
claim: ClaimedDynamicToolSettlement,
timeout: Duration,
) -> Result<()> {
let ack = self
.spawn_dynamic_tool_settlement(claim, DynamicToolTerminalOutcome::Timeout { timeout });
Self::await_dynamic_tool_settlement(ack).await?;
Ok(())
}
async fn settle_dynamic_tools_for_terminal_turn(
&self,
thread_id: &str,View on GitHub (pinned to 0c42157ee5)
Solutions
- If the error is a transient storage failure, the call was restored to Awaiting - fix storage and submit the result again with the same call_id
- If storage remains broken, stop and repair before any further settlement attempts
- Distinguish cases by follow-up behavior: a resubmit that returns Ok is the restored case; one that hits the 'indeterminate terminal receipt' bail means the rollback failed - inspect the JSONL log
- Capture the forwarded message; it names the append error or panic and points at the root cause
Defensive patterns
Strategy: try-catch
Try / catch
// Settlement failure: decide retry vs escalate by the follow-up state.
match manager.submit_dynamic_tool_result(thread_id, turn_id, call_id, result).await {
Ok(accepted) => Ok(accepted),
Err(e) => {
if e.to_string().contains("indeterminate terminal receipt") {
tracing::error!(%call_id, "append rollback failed; inspect storage, do not retry");
return Err(e); // terminal
}
// Retry-safe append failure restored the call to Awaiting: one retry is safe.
manager.submit_dynamic_tool_result(thread_id, turn_id, call_id, result).await
}
} Prevention
- Keep runtime store storage healthy; most forwarded errors are append I/O failures or panics
- Log the forwarded message verbatim - it names the root cause (append error or panic)
- After any settlement error, probe with a status/read call before deciding to retry
When it happens
Trigger: submit_dynamic_tool_result / timeout settlement / turn cancellation racing a storage failure during append_and_broadcast_event, or a panic inside the settlement future. The ack channel forwards the error text verbatim (runtime_threads.rs:4322-4329).
Common situations: Disk full or store directory removed mid-turn; broadcast/lock poisoning after shutdown; panics from serialization of an exotic payload.
Related errors
- Dynamic tool call '{call_id}' has an indeterminate terminal
- Dynamic tool settlement task ended before acknowledgement
- Turn {turn_id} has an indeterminate dynamic-tool receipt; re
- User-input request '{}' has an indeterminate terminal receip
- Runtime has reached the pending dynamic tool call limit ({MA
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/9aaf39b7f974faf0.
Report an issue: GitHub.