nautechsystems/nautilus_trader · error
Order {client_order_id} is already claimed by execution clie
Error message
Order {client_order_id} is already claimed by execution client {conflicting_client_id} and cannot be claimed by {client_id} What it means
During Postgres cache setup, index_order_clients (crates/infrastructure/src/sql/queries.rs:1345) claims persisted order_event rows for an execution client, backing the external_order_claims feature on strategies. Before updating, it selects any order_event row for the client_order_id already tagged with a different non-NULL client_id; if one exists it bails, because two execution clients must never own the same order.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:1369
for (client_order_id, client_id) in claims {
let conflicting_client_id = sqlx::query_scalar::<_, String>(
r#"
SELECT client_id
FROM "order_event"
WHERE client_order_id = $1
AND client_id IS NOT NULL
AND client_id <> $2
LIMIT 1
"#,
)
.bind(client_order_id.to_string())
.bind(client_id.to_string())
.fetch_optional(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to validate order client origin: {e}"))?;
if let Some(conflicting_client_id) = conflicting_client_id {
anyhow::bail!(
"Order {client_order_id} is already claimed by execution client \
{conflicting_client_id} and cannot be claimed by {client_id}"
);
}
sqlx::query(
r#"
INSERT INTO "client" (id)
VALUES ($1)
ON CONFLICT (id) DO NOTHING
"#,
)
.bind(client_id.to_string())
.execute(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to persist execution client {client_id}: {e}"))?;
let result = sqlx::query(View on GitHub (pinned to d1527c24af)
Solutions
- Configure external_order_claims with the same ClientId as the execution client that originally submitted those orders.
- Inspect existing ownership: SELECT DISTINCT client_id FROM order_event WHERE client_order_id = '...'; and reconcile the config to it.
- If re-assignment is genuinely intended, repair the persisted client_id on those order_event rows deliberately (backup first) or start with a clean database.
- Ensure exactly one node/strategy claims any given client_order_id.
Defensive patterns
Strategy: validation
Validate before calling
-- Run before starting the node with external_order_claims SELECT client_order_id, DISTINCT_ON (client_order_id) client_id FROM order_event WHERE client_order_id = ANY($1) -- your claimed order ids AND client_id IS NOT NULL ORDER BY client_order_id, created_at DESC; -- If any returned client_id differs from your configured ClientId, fix the config first.
Try / catch
if let Err(e) = node_builder.build().await {
let msg = e.to_string();
if msg.contains("already claimed by execution client") {
log::error!("external order claim conflicts with persisted ownership: {msg}");
// reconcile claim client_id with the persisted client_id before restarting
}
} Prevention
- Keep the ClientId in external_order_claims identical to the client that submitted the orders.
- Audit persisted client_id ownership with a one-line SQL query before changing claim configs.
- Never let two nodes or two client IDs claim the same client_order_id.
- Snapshot/backup the order_event table before any manual re-attribution.
When it happens
Trigger: Node startup (or an explicit index_order_clients call) with external order claims where a claim (ClientOrderId, ClientId) hits order_event rows already attributed to another client_id: configuring claims under a different execution client than the one that submitted the orders, or two strategies/configs claiming the same client_order_id through different clients.
Common situations: Changing the execution client ID configured for external order claims between runs without re-attributing database rows; copying a node configuration to another machine with a different client_id; both a venue client and a different client name claiming the same orders; renaming client IDs in config after orders were persisted.
Related errors
- No persisted order events found for {client_order_id}
- Timeout waiting for account {account_id} to be registered af
- Execution schema version {} is newer than supported version
- Failed to insert into execution_transaction table: {e}
- Failed to update execution hash {transaction_hash}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@d1527c24af (2026-08-21).
Data as JSON: /api/errors/8d037683c9699448.
Report an issue: GitHub.