nautechsystems/nautilus_trader · error · anyhow::Error
Conflicting execution client claims for {client_order_id}: {
Error message
Conflicting execution client claims for {client_order_id}: {existing_client_id} and {client_id} What it means
During batched execution-client claim registration, the same client_order_id appears twice in the claims list with two different ClientIds. The method builds an intermediate map and refuses inconsistent claims before any state is mutated, keeping the batch atomic.
Source
Thrown at crates/common/src/cache/mod.rs:4848
/// claim is idempotent, and a conflicting claim is rejected. The complete batch is validated
/// and its persistence command is successfully enqueued before any in-memory index is
/// changed.
///
/// # Errors
///
/// Returns an error if an order is not cached, an order is already claimed by another client,
/// the same order has conflicting claims in the batch, or persistence cannot be enqueued.
pub fn claim_order_clients(
&mut self,
claims: &[(ClientOrderId, ClientId)],
) -> anyhow::Result<()> {
let mut requested = AHashMap::with_capacity(claims.len());
let mut ordered_claims = Vec::with_capacity(claims.len());
for (client_order_id, client_id) in claims {
if let Some(existing_client_id) = requested.get(client_order_id) {
if existing_client_id != client_id {
anyhow::bail!(
"Conflicting execution client claims for {client_order_id}: \
{existing_client_id} and {client_id}"
);
}
continue;
}
requested.insert(*client_order_id, *client_id);
ordered_claims.push((*client_order_id, *client_id));
}
let mut pending_claims = Vec::with_capacity(ordered_claims.len());
for (client_order_id, client_id) in ordered_claims {
if !self.orders.contains_key(&client_order_id) {
return Err(OrderLookupError::not_found(client_order_id).into());
}
match self.index.order_client.get(&client_order_id) {View on GitHub (pinned to 18893faf8b)
Solutions
- Deduplicate/merge the claims list so each client_order_id appears once with a single ClientId.
- Fix the source that assigns the wrong client for that order.
- If the batch comes from config, make client routing deterministic for each order.
Defensive patterns
Strategy: validation
Validate before calling
let mut seen: AHashMap<ClientOrderId, ClientId> = AHashMap::default();
for (coid, cid) in &claims {
if let Some(prev) = seen.get(coid) {
if prev != cid { /* resolve conflict before batch registration */ }
} else { seen.insert(coid.clone(), cid.clone()); }
} Prevention
- Merge claim lists through one deduplicating merge step.
- Keep order-to-client routing deterministic in config.
- Avoid registering the same order from multiple adapters.
When it happens
Trigger: Calling `add_execution_client_claims`-style registration with a claims list containing the same client_order_id mapped to different clients; building the list from two sources (e.g. config + reconciliation) that disagree on ownership.
Common situations: Merging claim lists from multiple execution clients after reconnect; a config error routing one order to two clients; adapter reconciliation producing overlapping claim sets.
Related errors
- Order {client_order_id} is already claimed by execution clie
- Invalid config type for AxExecutionClientFactory. Expected A
- Replacement hash {transaction_hash} conflicts with another i
- DataActor {} must be registered before calling `cache()` - t
- Order {client_order_id} not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/09219908f2166b87.
Report an issue: GitHub.