nautechsystems/nautilus_trader · error · anyhow::Error

Existing {existing_venue_order_id} for {client_order_id}

Error message

Existing {existing_venue_order_id} for {client_order_id}
                    did not match the given {venue_order_id}.
                    If you are writing a test then try a different `venue_order_id`,
                    otherwise this is probably a bug.

What it means

When adding a venue order ID for a client order ID, the cache already has a different venue order ID mapped and `overwrite` is false. The cache treats a client_order_id -> venue_order_id mapping as immutable unless explicitly overwritten, so a mismatch is rejected as a likely bug or test artifact.

Source

Thrown at crates/common/src/cache/mod.rs:4656

            .entry(*client_order_id)
            .or_insert(*venue_order_id);

        Ok(())
    }

    fn validate_venue_order_id_claim(
        &self,
        client_order_id: &ClientOrderId,
        venue_order_id: &VenueOrderId,
        overwrite: bool,
    ) -> anyhow::Result<()> {
        self.validate_venue_order_id_ownership(client_order_id, venue_order_id)?;

        if let Some(existing_venue_order_id) = self.index.client_order_ids.get(client_order_id)
            && !overwrite
            && existing_venue_order_id != venue_order_id
        {
            anyhow::bail!(
                "Existing {existing_venue_order_id} for {client_order_id}
                    did not match the given {venue_order_id}.
                    If you are writing a test then try a different `venue_order_id`,
                    otherwise this is probably a bug."
            );
        }

        Ok(())
    }

    fn validate_venue_order_id_ownership(
        &self,
        client_order_id: &ClientOrderId,
        venue_order_id: &VenueOrderId,
    ) -> anyhow::Result<()> {
        if let Some(existing_client_order_id) = self.index.venue_order_ids.get(venue_order_id)
            && existing_client_order_id != client_order_id
        {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass `overwrite: true` if the venue legitimately reassigned the order ID.
  2. In tests, use a unique venue_order_id per client_order_id (as the message suggests).
  3. Verify which venue_order_id the adapter reports; fix the adapter mapping if it is wrong.

Example fix

// before
cache.add_venue_order_id(&client_order_id, venue_order_id, venue_order_id_assigned, false);
// after
cache.add_venue_order_id(&client_order_id, venue_order_id, venue_order_id_assigned, true); // if reassignment is intended
Defensive patterns

Strategy: try-catch

Validate before calling

if let Some(existing) = cache.venue_order_id(&client_order_id) {
    if existing != venue_order_id && !overwrite { /* handle mismatch before calling */ }
}

Try / catch

match cache.add_venue_order_id(&client_order_id, venue_order_id, ts, overwrite) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("did not match the given") => {
        // retry with overwrite=true or fix the venue_order_id
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `add_venue_order_id` (or `update_venue_order_id` with overwrite=false) for a client_order_id that already maps to another venue_order_id; reusing a client_order_id across tests or order generations; venue assign/re-assign flows that pass overwrite=false.

Common situations: Test code reusing fixture client order IDs while generating sequential venue order IDs; sim replay of fills with a stale venue order ID; adapter emitting a different venue order ID for the same client order after amend.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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