{"record":{"id":"c43005d3191ef3cf","repo":"Hmbown/CodeWhale","slug":"runtime-turn-interruption-failed-error","errorCode":null,"errorMessage":"Runtime turn interruption failed: {error}","messagePattern":"Runtime turn interruption failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":5199,"sourceCode":"                    .iter()\n                    .filter_map(|(id, state)| {\n                        state\n                            .active_turn\n                            .as_ref()\n                            .map(|turn| (id.clone(), turn.turn_id.clone()))\n                    })\n                    .collect::<Vec<_>>(),\n            )\n        };\n        let mut failure = None;\n        for (thread_id, turn_id) in active_turns {\n            if let Err(error) = self.interrupt_turn(&thread_id, &turn_id).await\n                && !self\n                    .store\n                    .load_turn(&turn_id)\n                    .is_ok_and(|turn| turn.status != RuntimeTurnStatus::InProgress)\n            {\n                failure = Some(anyhow!(\"Runtime turn interruption failed: {error}\"));\n            }\n        }\n        let workers = self.engine_workers.lock().clone();\n        for engine in engines\n            .iter()\n            .chain(workers.iter().map(|(engine, _)| engine))\n        {\n            engine.cancel_with_reason(crate::core::engine::CancelReason::Internal);\n        }\n        for engine in engines\n            .iter()\n            .chain(workers.iter().map(|(engine, _)| engine))\n        {\n            let _ = engine.send(Op::Shutdown).await;\n        }\n        for (_, worker) in workers {\n            if let Err(error) = await_retained_completion(&worker).await {\n                failure = Some(anyhow!(\"Runtime engine shutdown failed: {error}\"));","sourceCodeStart":5181,"sourceCodeEnd":5217,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L5181-L5217","documentation":"During RuntimeThreadManager shutdown, each active turn is interrupted via interrupt_turn. If that fails AND the persisted turn is still InProgress, the manager records 'Runtime turn interruption failed' as the shutdown failure it eventually returns. It only counts as a failure when the turn genuinely never left the InProgress state, so a benign interrupt error that still left a terminal turn record is ignored.","triggerScenarios":"Calling RuntimeThreadManager::shutdown while a turn is in flight and interrupt_turn (thread_id, turn_id) returns Err; additionally the store.load_turn check finds turn.status == RuntimeTurnStatus::InProgress, meaning the interrupt did not persist a terminal status.","commonSituations":"Shutting the runtime down while a model stream is still running; a wedged engine task that never responds to the interrupt; a storage error that prevents the turn record from being updated before shutdown.","solutions":["Inspect the wrapped {error} from interrupt_turn to find the root cause (engine channel, engine not installed, etc.)","Ensure turns reach a terminal status before shutdown: await or cancel the in-flight turn first","Verify the turn store is writable and load_turn can read the turn record","Retry shutdown after the engine worker has drained; the error is recorded only while the turn is stuck InProgress"],"exampleFix":"// before\nlet _ = manager.shutdown().await; // swallows nothing; error surfaces here\n// after\nfor (thread_id, turn_id) in manager.active_turns().await {\n    manager.interrupt_turn(&thread_id, &turn_id).await?;\n}\nmanager.shutdown().await?;","handlingStrategy":"try-catch","validationCode":"let turn = manager.store.load_turn(&turn_id)?;\nif turn.status == RuntimeTurnStatus::InProgress { /* shutdown will interrupt; prepare for possible failure */ }","typeGuard":"fn turn_is_terminal(status: RuntimeTurnStatus) -> bool { status != RuntimeTurnStatus::InProgress }","tryCatchPattern":"match manager.shutdown().await {\n    Err(e) if e.to_string().contains(\"interruption failed\") => {\n        // turn stuck InProgress: inspect interrupt_turn error inside {error}\n        tracing::error!(\"turn interruption failed: {e:#}\");\n    }\n    other => other?,\n}","preventionTips":["Complete or interrupt in-flight turns before calling shutdown","Persist a terminal turn status on every turn exit path","Monitor store health so load_turn writes/reads do not fail during shutdown"],"tags":["shutdown","async","turn-lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}