nautechsystems/nautilus_trader · error · anyhow::Error
External order claim for {instrument_id} already exists for
Error message
External order claim for {instrument_id} already exists for {existing} What it means
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.
Source
Thrown at crates/common/src/cache/mod.rs:2381
/// Returns an error if an instrument is repeated or claimed by another strategy.
pub fn set_external_order_claims(
&mut self,
strategy_id: StrategyId,
instrument_ids: &[InstrumentId],
) -> anyhow::Result<()> {
let mut requested = AHashSet::with_capacity(instrument_ids.len());
for instrument_id in instrument_ids {
if !requested.insert(*instrument_id) {
anyhow::bail!(
"External order claim for {instrument_id} appears more than once for {strategy_id}"
);
}
if let Some(existing) = self.external_order_claims.get(instrument_id)
&& *existing != strategy_id
{
anyhow::bail!(
"External order claim for {instrument_id} already exists for {existing}"
);
}
}
self.external_order_claims
.retain(|_, owner| *owner != strategy_id);
self.external_order_claims.extend(
requested
.into_iter()
.map(|instrument_id| (instrument_id, strategy_id)),
);
Ok(())
}
/// Adds external order claims for `strategy_id` without replacing its existing claims.
///View on GitHub (pinned to 18893faf8b)
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
Example fix
// before strategy_a.claim_external_orders(&[btc_usd])?; strategy_b.claim_external_orders(&[btc_usd])?; // bails // after strategy_a.claim_external_orders(&[btc_usd])?; // single owner // remove btc_usd from strategy_b's claim list
Defensive patterns
Strategy: validation
Validate before calling
for id in instruments {
if let Some(existing) = existing_claims.get(id) && *existing != strategy_id {
return Err(anyhow::anyhow!("{id} already claimed by {existing}"));
}
} Try / catch
if let Err(e) = cache.claim_external_orders(strategy_id, &instruments) {
if e.to_string().contains("already exists for") {
log::error!("instrument claim conflict: {e}; review strategy configs");
return Err(e);
} else { return Err(e); }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- External order claim for {instrument_id} appears more than o
- Conflicting execution client claims for {client_order_id}: {
- Instrument {instrument_id} not found in cache
- Failed to query order {}: {}
- Cannot modify order: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5189046cbaf4719c.
Report an issue: GitHub.