{"record":{"id":"8cf92b840ed2ae15","repo":"xai-org/grok-build","slug":"cannot-repair-history-while-a-turn-is-in-flight-s","errorCode":null,"errorMessage":"cannot repair history while a turn is in flight; stop the turn first","messagePattern":"cannot repair history while a turn is in flight; stop the turn first","errorType":"error_code","errorClass":"RepairHistoryBlocked","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-shell/src/session/acp_session_impl/rewind.rs","lineNumber":597,"sourceCode":"    /// the chat-state actor, then flush persistence so `chat_history.jsonl`\n    /// is rewritten on disk before the caller sees success.\n    ///\n    /// Refused while a turn is in flight (in-flight tool calls legitimately\n    /// await their results). The refusal is enforced inside the chat-state\n    /// actor's command handler — see `ChatStateCommand::RepairHistory` for\n    /// why a caller-side check alone would race turn start; the check below\n    /// is just a fast path.\n    pub(super) async fn handle_repair_history(\n        &self,\n        dry_run: bool,\n    ) -> anyhow::Result<xai_chat_state::compaction_utils::HistoryRepairReport> {\n        // Per-session flag — NOT `tool_context.is_turn_active`, which is the\n        // agent-wide coordinator flag shared by all sessions (using it would\n        // refuse repair of an idle session while any other session runs a\n        // turn, and another session's turn end could clear it mid-turn).\n        let turn_flag = self.session_turn_active.clone();\n        if turn_flag.load(std::sync::atomic::Ordering::SeqCst) {\n            anyhow::bail!(xai_chat_state::commands::RepairHistoryBlocked);\n        }\n\n        let report = self\n            .chat_state_handle\n            .repair_history(dry_run, Some(turn_flag))\n            .await\n            .ok_or_else(|| anyhow::anyhow!(\"chat-state actor unavailable\"))?\n            .map_err(anyhow::Error::new)?;\n\n        if report.changed() && !dry_run {\n            // Flush barrier: success must mean the rewrite is on disk.\n            let (flush_tx, flush_rx) = tokio::sync::oneshot::channel();\n            if self\n                .notifications\n                .persistence_tx\n                .send(PersistenceMsg::FlushAndAck {\n                    respond_to: flush_tx,\n                })","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-shell/src/session/acp_session_impl/rewind.rs#L579-L615","documentation":"Error \"cannot repair history while a turn is in flight; stop the turn first\" thrown in xai-org/grok-build.","triggerScenarios":"Thrown at crates/codegen/xai-grok-shell/src/session/acp_session_impl/rewind.rs:597 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}