{"record":{"id":"5189046cbaf4719c","repo":"nautechsystems/nautilus_trader","slug":"external-order-claim-for-instrument-id-already-e","errorCode":null,"errorMessage":"External order claim for {instrument_id} already exists for {existing}","messagePattern":"External order claim for (.+?) already exists for (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/cache/mod.rs","lineNumber":2381,"sourceCode":"    /// Returns an error if an instrument is repeated or claimed by another strategy.\n    pub fn set_external_order_claims(\n        &mut self,\n        strategy_id: StrategyId,\n        instrument_ids: &[InstrumentId],\n    ) -> anyhow::Result<()> {\n        let mut requested = AHashSet::with_capacity(instrument_ids.len());\n\n        for instrument_id in instrument_ids {\n            if !requested.insert(*instrument_id) {\n                anyhow::bail!(\n                    \"External order claim for {instrument_id} appears more than once for {strategy_id}\"\n                );\n            }\n\n            if let Some(existing) = self.external_order_claims.get(instrument_id)\n                && *existing != strategy_id\n            {\n                anyhow::bail!(\n                    \"External order claim for {instrument_id} already exists for {existing}\"\n                );\n            }\n        }\n\n        self.external_order_claims\n            .retain(|_, owner| *owner != strategy_id);\n        self.external_order_claims.extend(\n            requested\n                .into_iter()\n                .map(|instrument_id| (instrument_id, strategy_id)),\n        );\n\n        Ok(())\n    }\n\n    /// Adds external order claims for `strategy_id` without replacing its existing claims.\n    ///","sourceCodeStart":2363,"sourceCodeEnd":2399,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/cache/mod.rs#L2363-L2399","documentation":"External order claims map each `InstrumentId` to exactly one strategy. When claiming, if the instrument is already claimed by a different strategy, the call bails so two strategies cannot both own external order claims for the same instrument.","triggerScenarios":"Calling `claim_external_orders` with an instrument that `external_order_claims` already maps to a different strategy_id; two strategies configuring claims over the same instrument.","commonSituations":"Strategy configuration overlap where both strategies list the same symbol for external order claiming; reconfiguring strategies without clearing prior claims; loading the same config twice under different strategy IDs.","solutions":["Remove the overlapping instrument from one strategy's external-claim list","Use the same strategy for all external orders on that instrument","Clear the existing claim (via the appropriate unclaim/release path or fresh cache) before re-claiming with a different strategy","Audit strategy configs at startup to detect instrument overlaps early"],"exampleFix":"// before\nstrategy_a.claim_external_orders(&[btc_usd])?;\nstrategy_b.claim_external_orders(&[btc_usd])?; // bails\n// after\nstrategy_a.claim_external_orders(&[btc_usd])?; // single owner\n// remove btc_usd from strategy_b's claim list","handlingStrategy":"validation","validationCode":"for id in instruments {\n    if let Some(existing) = existing_claims.get(id) && *existing != strategy_id {\n        return Err(anyhow::anyhow!(\"{id} already claimed by {existing}\"));\n    }\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = cache.claim_external_orders(strategy_id, &instruments) {\n    if e.to_string().contains(\"already exists for\") {\n        log::error!(\"instrument claim conflict: {e}; review strategy configs\");\n        return Err(e);\n    } else { return Err(e); }\n}","preventionTips":["Ensure each instrument is claimed by at most one strategy","Audit strategy configs for overlapping external-claim instruments","Clear stale claims before reassigning instruments to a new strategy"],"tags":["cache","conflict","orders","claims"],"backgroundTag":"conflicting-config-options","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"}