Hmbown/CodeWhale · error
operation_key binding is incomplete; retry after Runtime…
Error message
operation_key binding is incomplete; retry after Runtime recovery
What it means
Durability guard in the turn-operation binding check: a persisted binding exists for the operation key fingerprint, but the turn file it points to is missing or incomplete on disk. The binding record and the turn store disagree, which normally means a crash mid-write; Runtime recovery (or replay) is expected to reconcile them.
Solutions
- Retry the turn start after Runtime recovery completes and the binding is repaired.
- Inspect the turn store for the partially persisted turn and reconcile or remove the stale binding.
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at crates/tui/src/runtime_threads.rs:9068 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/e9d71c332aa7d474.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:9068
let Some(persisted) = self
.store
.load_turn_operation_binding(&requested.operation_key_fingerprint)?
else {
return Ok(None);
};
if persisted.thread_id != requested.thread_id
|| persisted.operation_key_fingerprint != requested.operation_key_fingerprint
|| persisted.request_fingerprint != requested.request_fingerprint
|| prepared
.requested_turn_id
.as_deref()
.is_some_and(|turn_id| persisted.turn_id != turn_id)
{
bail!("operation_key is already bound to a different turn request");
}
let turn_path = self.store.turn_path(&persisted.turn_id)?;
if !turn_path.exists() {
bail!("operation_key binding is incomplete; retry after Runtime recovery");
}
let turn = self.store.load_turn(&persisted.turn_id)?;
if turn.id != persisted.turn_id || turn.thread_id != persisted.thread_id {
bail!("operation_key binding does not match its persisted Runtime turn");
}
Ok(Some(turn))
}
/// Read the exact durable binding without replaying, recovering, loading an
/// engine, or creating even a claim-lock file. The shared claim prevents a
/// reader from observing admission records that can still be rolled back.
pub(crate) fn lookup_turn_operation(
&self,
thread_id: &str,
operation_key: &str,
) -> Result<Option<TurnRecord>, RuntimeTurnOperationLookupError> {
use RuntimeTurnOperationLookupError::{Incomplete, InvalidRequest, Unavailable};
validated_record_id(thread_id, "thread id").map_err(|_| InvalidRequest)?;View on GitHub (pinned to 73e0f67d83)