nautechsystems/nautilus_trader · error

venue order {venue_order_id} has contradictory client associ

Error message

venue order {venue_order_id} has contradictory client associations {known} and {candidate}

What it means

`resolve_target_order_authority` collects every client-order-id candidate associated with a venue order (report payload, cached index, cached order). The first candidate fixes the association; any subsequent candidate that differs means the venue order is linked to two different client orders, which would make report routing ambiguous, so the adapter fails with `anyhow::ensure!`.

Source

Thrown at crates/adapters/polymarket/src/execution/reports.rs:117

    fn resolve_target_order_authority(
        &self,
        explicit_client_order_id: Option<ClientOrderId>,
        venue_order_id: VenueOrderId,
        requested_instrument_id: Option<InstrumentId>,
    ) -> anyhow::Result<TargetOrderAuthority> {
        let context = self.order_contexts.get(&venue_order_id);
        let cached_client_order_id = self.core.cache().client_order_id(&venue_order_id).copied();

        let mut client_order_id = explicit_client_order_id;
        for candidate in [
            context.map(|value| value.identity.client_order_id),
            cached_client_order_id,
        ]
        .into_iter()
        .flatten()
        {
            if let Some(known) = client_order_id {
                anyhow::ensure!(
                    candidate == known,
                    "venue order {venue_order_id} has contradictory client associations {known} and {candidate}",
                );
            } else {
                client_order_id = Some(candidate);
            }
        }

        if let Some(client_order_id) = client_order_id
            && let Some(registered_venue_order_id) =
                self.order_contexts.venue_order_id(&client_order_id)
        {
            anyhow::ensure!(
                registered_venue_order_id == venue_order_id,
                "client order {client_order_id} is registered to venue order {registered_venue_order_id}, not requested venue order {venue_order_id}",
            );
        }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the two reported client ids ({known} and {candidate}) in the message and purge the stale/incorrect association from the execution cache for that venue_order_id.
  2. Make client_order_id generation deterministic or collision-free across restarts (e.g. derive from venue order id or use a persistent UUID source) so reloaded orders keep their original association.
  3. Run reconciliation/cache rebuild so cached index and cached order agree before querying order status or fill reports for that venue order.
  4. If reports were replayed with remapped client ids, re-ingest with the original client_order_id mapping intact.

Example fix

// before: nondeterministic client ids per run cause contradictory associations
client_order_id = self.order_factory.generate_client_order_id()  // new each restart
// after: stable mapping so a venue order always resolves to one client id
client_order_id = persisted_mapping.get(venue_order_id)
    or self.order_factory.generate_client_order_id();
persisted_mapping.insert(venue_order_id, client_order_id);
Defensive patterns

Strategy: validation

Validate before calling

candidates = {
    report.client_order_id,
    cache.client_order_id_for_venue_order(venue_order_id),
    cached_order.client_order_id if cached_order else None,
} - {None}
if len(candidates) > 1:
    raise ValueError(
        f"venue order {venue_order_id} maps to multiple client ids {candidates}; "
        "rebuild cache before querying reports"
    )

Type guard

def has_unambiguous_client_association(venue_order_id, cache) -> bool:
    candidates = {
        cid for cid in (
            cache.client_order_id_for_venue_order(venue_order_id),
        )
        if cid is not None
    }
    return len(candidates) <= 1

Try / catch

try:
    reports = client.generate_order_status_reports(venue_order_id=venue_order_id)
except Exception as e:
    if "contradictory client associations" in str(e):
        log.error("venue order %s linked to multiple client ids; "
                  "purge stale cache entry or make client ids stable across restarts", venue_order_id)
    raise

Prevention

When it happens

Trigger: Raised in `resolve_target_order_authority` (called by query_order_command, generate_order_status_report_impl, generate_fill_reports_impl) when, for one venue_order_id, at least two distinct client_order_ids are derivable — e.g. a venue order id was reused across strategy restarts with fresh client ids, a client id collided, or cached index entries disagree with the incoming report.

Common situations: Reusing the same Polymarket venue order across strategy instances that each minted a different client_order_id; restoring a cache partially so the index and cached order disagree; client_order_id generation not unique after restart; manually replaying archived reports with remapped client ids.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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