Hmbown/CodeWhale · error
Thread execution settings changed while preparing the turn…
Error message
Thread execution settings changed while preparing the turn; retry
What it means
After goal verification, the runtime reloads the thread record under the thread-mutation lock and compares its execution settings (model, route, etc.) with the snapshot the request was built from via thread_execution_state_matches. A mismatch means the thread's configuration moved mid-flight, so the turn is refused rather than run with stale settings.
Solutions
- Retry with a freshly loaded thread so the request snapshot matches current settings.
- Avoid changing thread execution settings while a turn is being prepared.
- If the change was intentional, cancel the in-flight submission and start a new turn from current state.
Example fix
// before let thread = store.load_thread(id)?; spawn(set_thread_model(id, "new-model")); submit_turn(thread, req)?; // may mismatch // after let thread = store.load_thread(id)?; submit_turn(thread, req).await?; set_thread_model(id, "new-model").await?;
Defensive patterns
Strategy: retry
Validate before calling
let current = store.load_thread(thread_id)?;
if !thread_execution_state_matches(&thread_snapshot, ¤t) {
thread_snapshot = current; // rebuild request from fresh thread
} Try / catch
match submit_turn(id, req).await {
Err(e) if e.to_string().contains("settings changed") => {
let fresh = store.load_thread(id)?;
submit_turn(id, req_for(fresh)).await
}
other => other,
} Prevention
- Pause settings/model changes while a turn submission is in flight.
- Apply execution-setting changes only between turns.
- Always load the thread record at submission time rather than caching it.
When it happens
Trigger: Changing the thread's model/execution settings (e.g. via a settings API or UI switch) after the request snapshot was taken but before turn registration completed.
Common situations: User flips model or provider mid-submission; a background job rewrites thread config; hot-swapping route settings while a queued turn fires.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Goal changed while preparing the turn; retry
- Runtime turn operation is already being claimed; retry
- A saved trace identifier collided. Try saving again.
- a window change is already in progress
- another Codewhale process
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/6a21e0f170485954.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:10249
&& let Some(original_turn) = self.replay_turn_for_operation(operation)?
{
return Ok((original_turn, true));
}
let Some(state) = active.engines.get_mut(thread_id) else {
bail!("Thread engine not loaded");
};
if state.active_turn.is_some() {
bail!("Thread already has an active turn");
}
let _goal_mutation = self.store.goal_mutation.lock();
if self.store.load_goal(thread_id)? != turn_goal {
bail!("Goal changed while preparing the turn; retry");
}
engine.restore_runtime_goal(turn_goal.as_ref())?;
let _thread_mutation = self.store.thread_mutation.lock();
let mut current_thread = self.store.load_thread(thread_id)?;
if !thread_execution_state_matches(&thread, ¤t_thread) {
bail!("Thread execution settings changed while preparing the turn; retry");
}
let previous_active_route = (state.route_identity.clone(), state.route_model.clone());
state.active_turn = Some(ActiveTurnState {
goal_id: turn_goal.as_ref().map(|goal| goal.goal_id.clone()),
turn_id: turn_id.clone(),
interrupt_requested: false,
compaction_id: None,
});
state.route_identity = provider_identity;
state.route_model.clone_from(&model);
let persistence_result = (|| -> Result<()> {
if let Some(operation) = operation.as_ref() {
self.store
.save_turn_operation_binding(&operation.binding)?;
}
self.store.save_item(&user_item)?;
self.store.save_turn(&turn)?;View on GitHub (pinned to 73e0f67d83)