Hmbown/CodeWhale · error

Failed to persist steer: {error}; cleanup also failed: {clea

Error message

Failed to persist steer: {error}; cleanup also failed: {cleanup_error}

What it means

Compound sentinel from steer persistence: the closure that loads the turn, verifies it is still InProgress, saves the steer item and updated turn record failed (persistence_error), and the compensating remove_item rollback in the Err arm also failed (cleanup_error). The store may now contain a steer item whose turn record was not updated.

Source

Thrown at crates/tui/src/runtime_threads.rs:6305

                let mut turn = self.store.load_turn(turn_id)?;
                if turn.status != RuntimeTurnStatus::InProgress {
                    bail!("Turn {turn_id} is no longer in progress and cannot be steered");
                }
                self.store.save_item(&item)?;
                turn.steer_count = turn.steer_count.saturating_add(1);
                if !turn.item_ids.iter().any(|id| id == &item.id) {
                    turn.item_ids.push(item.id.clone());
                }
                self.store.save_turn(&turn)?;
                Ok(turn)
            })();
            let turn = match persistence {
                Ok(turn) => turn,
                Err(error) => {
                    let cleanup = self.store.remove_item(&item.id);
                    return match cleanup {
                        Ok(()) => Err(error),
                        Err(cleanup_error) => Err(anyhow!(
                            "Failed to persist steer: {error}; cleanup also failed: {cleanup_error}"
                        )),
                    };
                }
            };
            // The reserved send has no await/failure point. From here the
            // engine and durable record agree even if the API caller drops.
            let _sender = permit.send(prompt.clone());
            touch_lru(&mut active.lru, thread_id);
            self.spawn_steer_receipts(turn, item, prompt)
        };
        receipt_rx
            .await
            .map_err(|_| anyhow!("Steer receipt task ended before acknowledgement"))
    }

    pub async fn compact_thread(
        &self,

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Fix the underlying store error (turn no longer InProgress is a benign race; treat as a lost steer and re-send the message)
  2. If cleanup failed, inspect the store for the orphaned item id and remove it before steering again
  3. Ensure only one process is steering the same turn concurrently
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at crates/tui/src/runtime_threads.rs:6305 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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