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

  1. Treat the IDEMPOTENT_DUPLICATE prefix specially: query the open-order state by clOrdID instead of resubmitting with the same ID
  2. On retry, fetch order status first (or use amend/query) rather than blind resubmit
  3. If the order should be new, generate a fresh clOrdID only after confirming the original is truly absent
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/ae85eedf2254436c. Report an issue: GitHub.