{"record":{"id":"6a21e0f170485954","repo":"Hmbown/CodeWhale","slug":"thread-execution-settings-changed-while-preparing","errorCode":null,"errorMessage":"Thread execution settings changed while preparing the turn; retry","messagePattern":"Thread execution settings changed while preparing the turn; retry","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":6120,"sourceCode":"            .clone()\n            .reserve_owned()\n            .await\n            .map_err(|_| anyhow!(\"Failed to start turn: engine operation channel closed\"))?;\n\n        let acceptance_rx = {\n            // Lock order is active -> thread_mutation. Neither guard crosses\n            // an await, and spawning the owned lifecycle task is synchronous.\n            let mut active = self.active.lock().await;\n            let Some(state) = active.engines.get_mut(thread_id) else {\n                bail!(\"Thread engine not loaded\");\n            };\n            if state.active_turn.is_some() {\n                bail!(\"Thread already has an active turn\");\n            }\n            let _thread_mutation = self.store.thread_mutation.lock();\n            let mut current_thread = self.store.load_thread(thread_id)?;\n            if !thread_execution_state_matches(&thread, &current_thread) {\n                bail!(\"Thread execution settings changed while preparing the turn; retry\");\n            }\n            let previous_active_route = (state.route_identity.clone(), state.route_model.clone());\n            state.active_turn = Some(ActiveTurnState {\n                turn_id: turn_id.clone(),\n                interrupt_requested: false,\n                compaction_id: None,\n            });\n            state.route_identity = provider_identity;\n            state.route_model.clone_from(&model);\n\n            let persistence_result = (|| -> Result<()> {\n                self.store.save_item(&user_item)?;\n                self.store.save_turn(&turn)?;\n                current_thread.latest_turn_id = Some(turn_id.clone());\n                current_thread.updated_at = now;\n                self.store.save_thread(&current_thread)\n            })();\n            if let Err(persistence_error) = persistence_result {","sourceCodeStart":6102,"sourceCodeEnd":6138,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/runtime_threads.rs#L6102-L6138","documentation":"Start-turn race detection: the thread's execution settings (mode/posture) changed between preparing the turn and claiming it under the active lock. Rather than running a turn with a stale policy snapshot, the start aborts and the caller is told to retry with the new settings.","triggerScenarios":"Thrown at crates/tui/src/runtime_threads.rs:6120 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry the turn start — it will pick up the new settings","Avoid changing execution settings concurrently with turn starts"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}