{"record":{"id":"636e29ece4c5c450","repo":"Hmbown/CodeWhale","slug":"failed-to-trigger-compaction-engine-operation-cha","errorCode":null,"errorMessage":"Failed to trigger compaction: engine operation channel closed","messagePattern":"Failed to trigger compaction: engine operation channel closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":10609,"sourceCode":"                &route_model,\n            )),\n            routed_usage: Vec::new(),\n            routed_usage_drop_records: Vec::new(),\n            routed_usage_source_ids: Vec::new(),\n            routed_usage_dropped_records: 0,\n            model_request_diagnostics: None,\n            error: None,\n            item_ids: Vec::new(),\n            steer_count: 0,\n            agent_mail_message_id: None,\n        };\n        let op = Op::CompactContext {\n            id: compaction_id.clone(),\n            route: Box::new(route),\n            compaction: Box::new(compaction),\n        };\n        let permit = engine.tx_op.clone().reserve_owned().await.map_err(|_| {\n            anyhow!(\"Failed to trigger compaction: engine operation channel closed\")\n        })?;\n\n        let acceptance_rx = {\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 compaction; retry\");\n            }\n            let previous_active_route = (state.route_identity.clone(), state.route_model.clone());\n            state.active_turn = Some(ActiveTurnState {\n                goal_id: None,","sourceCodeStart":10591,"sourceCodeEnd":10627,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L10591-L10627","documentation":"Raised when reserving a slot on the engine's operation channel (`tx_op.reserve_owned()`) fails while triggering a compaction, which can only happen if the channel is closed — i.e. the engine task has already terminated. Without a reserved permit the runtime cannot hand the Op::CompactContext operation to the engine, so it fails fast with this error instead of hanging.","triggerScenarios":"Calling `compact_thread` when the thread's engine worker task has exited (panicked, aborted during shutdown, or completed) so `engine.tx_op` is closed and `reserve_owned().await` returns Err.","commonSituations":"The engine worker crashed earlier (check logs for panics); the app is shutting down while compaction is requested; the thread's engine was reaped (LRU eviction/cleanup) between `ensure_engine_loaded` and the reserve.","solutions":["Retry compaction — `ensure_engine_loaded` will respawn a fresh engine if the old one died.","Check logs for an engine task panic and address its root cause.","Avoid triggering compaction during application shutdown.","If it reproduces on one thread, unload/reload that thread to rebuild its engine."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match runtime.compact_thread(&thread_id, req).await {\n    Err(e) if e.to_string().contains(\"operation channel closed\") => {\n        // engine died: reload thread / respawn engine, then retry compaction once\n    }\n    r => r?,\n}","preventionTips":["Fix engine worker panics reported in logs before retrying heavy operations.","Do not request compaction during application shutdown.","Reload threads whose engines have been idle-evicted.","Monitor engine worker health (worker completions are retained in runtime state)."],"tags":["compaction","channel-closed","engine","async"],"backgroundTag":"broken-pipe","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"}