{"record":{"id":"90bb5cf637d04cd9","repo":"nautechsystems/nautilus_trader","slug":"cannot-deregister-external-order-claims-e","errorCode":null,"errorMessage":"Cannot deregister external order claims: {e}","messagePattern":"Cannot deregister external order claims: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/live/src/node/mod.rs","lineNumber":2804,"sourceCode":"        }\n\n        Ok(())\n    }\n\n    /// Deregisters all external order claims owned by `strategy_id` from the shared cache.\n    ///\n    /// The operation is synchronous and can be called while the node is idle, after manual\n    /// [`start`](Self::start) returns, or after the node stops. It cannot be called while\n    /// [`run`](Self::run) or [`run_with_mode`](Self::run_with_mode) owns the node.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the cache is already borrowed.\n    pub fn deregister_external_order_claims(&self, strategy_id: StrategyId) -> anyhow::Result<()> {\n        self.kernel\n            .cache\n            .try_borrow_mut()\n            .map_err(|e| anyhow::anyhow!(\"Cannot deregister external order claims: {e}\"))?\n            .set_external_order_claims(strategy_id, &[])?;\n\n        Ok(())\n    }\n\n    pub(crate) fn rollback_external_order_claims(\n        &self,\n        strategy_id: StrategyId,\n        instrument_ids: &[InstrumentId],\n    ) -> anyhow::Result<()> {\n        let mut cache = self\n            .kernel\n            .cache\n            .try_borrow_mut()\n            .map_err(|e| anyhow::anyhow!(\"Cannot roll back external order claims: {e}\"))?;\n        let retained: Vec<_> = cache\n            .external_order_claim_instrument_ids(Some(strategy_id))\n            .into_iter()","sourceCodeStart":2786,"sourceCodeEnd":2822,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/node/mod.rs#L2786-L2822","documentation":"This error wraps a `RefCell::try_borrow_mut` failure on the kernel cache when `deregister_external_order_claims` attempts to clear a strategy's external order claims (it calls `set_external_order_claims(strategy_id, &[])`). The cache RefCell is already borrowed elsewhere on the same thread, so the mutable borrow fails. It is an aliasing/re-entrancy error, not a claim-related domain error.","triggerScenarios":"Calling `deregister_external_order_claims` while the kernel cache is borrowed — e.g. from inside an event/data callback holding a cache borrow, or while another node operation (like `add_strategy`) is mid-call on the same thread.","commonSituations":"Tearing down strategies from within their own `on_stop` handler while the cache borrow from dispatch is alive; interleaving strategy add/remove calls in async tasks sharing the node on one thread.","solutions":["Ensure the cache borrow is released (drop guards) before deregistering.","Perform deregistration outside callbacks, e.g. in the outer shutdown path.","Defer the call via a queue processed where no cache borrow is held.","Check the wrapped `e` text for the location of the conflicting borrow."],"exampleFix":"// before\n// inside on_stop while cache may be borrowed\nnode.deregister_external_order_claims(strategy_id)?;\n// after\n// schedule teardown outside the callback scope\ntelemetry_queue.push(TearDown::DeregisterClaims(strategy_id));","handlingStrategy":"try-catch","validationCode":"if node.kernel.cache.try_borrow().is_err() {\n    return Err(anyhow::anyhow!(\"cache already borrowed; defer claim deregistration\"));\n}","typeGuard":null,"tryCatchPattern":"match node.deregister_external_order_claims(strategy_id) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"Cannot deregister external order claims\") => {\n        // schedule teardown where no cache borrow is held\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Deregister claims outside strategy on_stop callbacks while node dispatch holds borrows","Centralize strategy add/remove in one owner scope","Keep cache borrow lifetimes short and scoped","Prefer the node's own teardown/shutdown path for cleanup"],"tags":["rust","refcell","borrow-conflict","cache"],"backgroundTag":"refcell-already-borrowed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}