nautechsystems/nautilus_trader · warning · anyhow::Error
IDEMPOTENT_DUPLICATE
IDEMPOTENT_DUPLICATE
Error message
IDEMPOTENT_DUPLICATE: Order likely exists but confirmation was lost
What it means
In process_submit_results, when every request in a broadcast submit returned BitMEX's 'Duplicate clOrdID' error, the library concludes the order most likely already exists on the exchange but the original success acknowledgment was lost (e.g. a dropped response after the order was accepted). It bails with a message prefixed IDEMPOTENT_DUPLICATE so callers can distinguish this idempotency case from genuine submission failures.
Source
Thrown at crates/adapters/bitmex/src/broadcast/submitter.rs:640
all_duplicate_clordid = false;
all_definitive_refusals = false;
log::warn!("{operation} task join error: {e:?}");
errors.push(format!("Task panicked: {e:?}"));
}
}
}
// All tasks failed
self.failed_submits.fetch_add(1, Ordering::Relaxed);
// If all errors were "Duplicate clOrdID", this is likely an idempotent scenario
// where the order exists but the success response was lost
if all_duplicate_clordid && !errors.is_empty() {
log::warn!(
"All {} requests returned 'Duplicate clOrdID' - order likely exists {params}",
operation.to_lowercase(),
);
anyhow::bail!("IDEMPOTENT_DUPLICATE: Order likely exists but confirmation was lost");
}
if all_definitive_refusals && !errors.is_empty() {
log::error!(
"All {} requests were refused by BitMEX: {errors:?} {params}",
operation.to_lowercase(),
);
anyhow::bail!(
"{DEFINITIVE_SUBMIT_REJECTION}: All {} requests were refused by BitMEX: {errors:?}",
operation.to_lowercase(),
);
}
log::error!(
"All {} requests failed: {errors:?} {params}",
operation.to_lowercase(),
);
Err(anyhow::anyhow!(View on GitHub (pinned to 18893faf8b)
Solutions
- Treat the IDEMPOTENT_DUPLICATE prefix specially: query the open-order state by clOrdID instead of resubmitting with the same ID
- On retry, fetch order status first (or use amend/query) rather than blind resubmit
- If the order should be new, generate a fresh clOrdID only after confirming the original is truly absent
- Deduplicate in-flight submits so the same clOrdID is not broadcast twice concurrently
Example fix
// before
match submitter.broadcast_submit(order).await {
Err(e) if e.to_string().contains("IDEMPOTENT_DUPLICATE") => {
// order probably exists — reconcile instead of failing
let existing = query_order_by_clordid(&order.cl_ord_id()).await?;
}
other => other?,
}
// after (avoid the case): reconcile before retry
if query_order_by_clordid(&cl_ord_id).await?.is_some() {
return Ok(OrderStatus::Existing);
}
submitter.broadcast_submit(order).await?; Defensive patterns
Strategy: try-catch
Validate before calling
// before resubmitting, check if the order already exists let exists = query_order_by_clordid(&cl_ord_id).await?.is_some();
Type guard
fn is_idempotent_duplicate(err: &anyhow::Error) -> bool {
err.to_string().starts_with("IDEMPOTENT_DUPLICATE")
} Try / catch
match submitter.broadcast_submit(&order).await {
Err(e) if is_idempotent_duplicate(&e) => {
// reconcile: the order likely exists on the exchange
let status = query_order_by_clordid(&order.cl_ord_id()).await?;
adopt_existing_order(status);
}
other => other?,
} Prevention
- Never blindly resubmit with the same clOrdID; query order state first
- Use unique, deterministic clOrdIDs to make retries idempotent
- Deduplicate in-flight submits across redundant transports
- Reconcile local order state with the exchange after disconnects
When it happens
Trigger: Re-broadcasting a submit (retry path) whose clientOrderID already exists on BitMEX; all transport replicas answer 'Duplicate clOrdID' and errors is non-empty, so all_duplicate_clordid is true.
Common situations: Retrying a submit after a websocket disconnect or timeout where the first request actually succeeded; running redundant transport connections where the same order reached BitMEX twice; replaying a submit log after a crash.
Related errors
- DEFINITIVE_SUBMIT_REJECTION
- OrderList denied: duplicate {order_list.id}
- Failed to reserve execution intent for signer {} on chain {}
- Failed to commit replacement transaction: {e}
- WS submit order failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ae85eedf2254436c.
Report an issue: GitHub.