{"record":{"id":"b3802b03aed4c7c3","repo":"nautechsystems/nautilus_trader","slug":"e-failed-to-roll-back-external-order-claims-for","errorCode":null,"errorMessage":"{e}; failed to roll back external order claims for {strategy_id}: {rollback_error}","messagePattern":"(.+?); failed to roll back external order claims for (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/live/src/node/mod.rs","lineNumber":2732,"sourceCode":"            self.register_external_order_claims(strategy_id, &instrument_ids)?;\n        }\n\n        let mut exec_engine = match oms_type\n            .map(|_| {\n                self.kernel\n                    .exec_engine\n                    .try_borrow_mut()\n                    .map_err(|e| anyhow::anyhow!(\"Cannot register OMS type: {e}\"))\n            })\n            .transpose()\n        {\n            Ok(exec_engine) => exec_engine,\n            Err(e) => {\n                if !instrument_ids.is_empty()\n                    && let Err(rollback_error) =\n                        self.rollback_external_order_claims(strategy_id, &instrument_ids)\n                {\n                    anyhow::bail!(\n                        \"{e}; failed to roll back external order claims for {strategy_id}: {rollback_error}\"\n                    );\n                }\n                return Err(e);\n            }\n        };\n\n        if let Err(add_error) = self.kernel.trader.borrow_mut().add_strategy(strategy) {\n            drop(exec_engine);\n\n            if !instrument_ids.is_empty()\n                && let Err(rollback_error) =\n                    self.rollback_external_order_claims(strategy_id, &instrument_ids)\n            {\n                anyhow::bail!(\n                    \"Failed to add strategy {strategy_id}: {add_error}; failed to roll back external order claims: {rollback_error}\"\n                );\n            }","sourceCodeStart":2714,"sourceCodeEnd":2750,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/node/mod.rs#L2714-L2750","documentation":"In `add_strategy`, when creating the exec engine fails, the node tries to roll back external order claims registered for the strategy's instrument IDs. If that rollback also fails, the original error is augmented with the rollback failure via `anyhow::bail!` so both causes are visible. This preserves the original failure context while surfacing that cleanup could not complete, meaning external order claims may be left dangling.","triggerScenarios":"Calling `add_strategy` where exec engine creation returns `Err(e)` AND `instrument_ids` is non-empty AND `rollback_external_order_claims` itself returns `Err(rollback_error)` (e.g. claim records missing, cache lock poisoned, or a persistence/redis failure during claim removal).","commonSituations":"A misconfigured strategy or unavailable data/exec client causes engine creation to fail, while the rollback path independently fails due to a broken cache/redis connection or the claims having already been partially removed by a previous failed attempt.","solutions":["Fix the root cause reported in the leading `{e}` part of the message (exec engine creation failure) first.","Inspect why rollback failed (trailing `{rollback_error}`): verify the cache/backing store used by external order claims is reachable and consistent.","Restart the node to clear any stale in-memory claim state, then re-add the strategy.","Check that instrument_ids passed to add_strategy are valid and that no concurrent add_strategy call is mutating the same claims."],"exampleFix":"// before: rollback failure is opaque\nanyhow::bail!(\"{e}; failed to roll back external order claims for {strategy_id}: {rollback_error}\");\n// after: caller ensures node is idle and cache healthy before adding\nassert_eq!(node.state(), NodeState::Idle);\nnode.connect_cache()?; // ensure backing cache reachable\nnode.add_strategy(strategy)?;","handlingStrategy":"try-catch","validationCode":"if node.state() != NodeState::Idle {\n    anyhow::bail!(\"node must be idle before add_strategy\");\n}","typeGuard":"fn can_add(node: &LiveNode) -> bool { node.state() == NodeState::Idle }","tryCatchPattern":"match node.add_strategy(strategy) {\n    Err(e) if e.to_string().contains(\"failed to roll back external order claims\") => {\n        // both engine creation and rollback failed: inspect inner rollback_error, restart node\n    }\n    Err(e) => return Err(e),\n    Ok(_) => {}\n}","preventionTips":["Ensure the cache/backing store is connected before adding strategies.","Keep add_strategy calls on a single thread to avoid claim races.","Monitor node state before mutating node configuration."],"tags":["rollback-failure","error-chaining","live-node","order-claims"],"backgroundTag":"invalid-state-transition","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"}