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

  1. 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
  2. If storage remains broken, stop and repair before any further settlement attempts
  3. 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
  4. 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

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


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/9aaf39b7f974faf0. Report an issue: GitHub.