{"record":{"id":"f1f5eb1c63af5be3","repo":"nautechsystems/nautilus_trader","slug":"cannot-register-external-order-claims-e","errorCode":null,"errorMessage":"Cannot register external order claims: {e}","messagePattern":"Cannot register external order claims: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/live/src/node/mod.rs","lineNumber":2781,"sourceCode":"    /// Registers external order claims in the shared cache.\n    ///\n    /// It can be called while the node is idle, after manual [`start`](Self::start) returns, or\n    /// after the node stops. A running strategy can update its own claims through\n    /// `Strategy::set_external_order_instrument_ids`.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error without changing the cache if the cache is already borrowed, the request\n    /// repeats an instrument, or any requested instrument already has a claim.\n    pub fn register_external_order_claims(\n        &self,\n        strategy_id: StrategyId,\n        instrument_ids: &[InstrumentId],\n    ) -> anyhow::Result<()> {\n        self.kernel\n            .cache\n            .try_borrow_mut()\n            .map_err(|e| anyhow::anyhow!(\"Cannot register external order claims: {e}\"))?\n            .register_external_order_claims(strategy_id, instrument_ids)?;\n\n        if !instrument_ids.is_empty() {\n            log::info!(\"Registered external order claims for {strategy_id}: {instrument_ids:?}\");\n        }\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.","sourceCodeStart":2763,"sourceCodeEnd":2799,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/node/mod.rs#L2763-L2799","documentation":"This error wraps a `RefCell::try_borrow_mut` failure when `register_external_order_claims` tries to mutably borrow the kernel's cache to register instrument-ID claims for a strategy. The cache is a shared `RefCell`; if it is already borrowed (mutably or immutably) on the same thread, the borrow fails and this message is raised. The inner `register_external_order_claims` call errors are propagated separately with their own messages.","triggerScenarios":"Calling `register_external_order_claims` (directly or via `add_strategy`) while the kernel cache RefCell is held — e.g. inside a data/event callback that has borrowed the cache, or nested registration calls on one thread.","commonSituations":"Adding strategies from within a running node's callbacks; user code holding `node.kernel.cache.borrow()` while adding strategies; re-entrant `add_strategy` from `on_start` of a previously registered strategy.","solutions":["Drop any live borrow of the kernel cache before calling this method.","Register external order claims during node setup, before `run()` starts the event loop.","Defer registration out of callbacks into the caller that owns the node.","Read the wrapped `e` message: Pyo3 reports where the conflicting borrow originates."],"exampleFix":"// before\nlet cache = node.kernel.cache.borrow();\nnode.register_external_order_claims(strategy_id, &ids)?;\n// after\ndrop(node.kernel.cache.borrow());\nnode.register_external_order_claims(strategy_id, &ids)?;","handlingStrategy":"try-catch","validationCode":"// Ensure the kernel cache is not currently borrowed\nif node.kernel.cache.try_borrow().is_err() {\n    return Err(anyhow::anyhow!(\"cache already borrowed; defer claim registration\"));\n}","typeGuard":null,"tryCatchPattern":"match node.register_external_order_claims(strategy_id, &ids) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"Cannot register external order claims\") => {\n        // release cache borrows and retry, or defer to setup phase\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Register external order claims before node.run() starts the event loop","Drop cache borrow guards promptly; never hold them across registration calls","Do not interleave add_strategy calls with code that borrows the cache","Queue registrations from callbacks and apply them in an outer scope"],"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-14T00:17:10.932Z"}