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
- 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.
- 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.
- Run reconciliation/cache rebuild so cached index and cached order agree before querying order status or fill reports for that venue order.
- 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
- Make client_order_id generation deterministic or collision-free across restarts
- Persist the venue_order_id -> client_order_id mapping alongside the cache
- Rebuild/reconcile the execution cache fully after restarts so index and cached orders agree
- Never replay archived reports with remapped client ids
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
- client-bound Polymarket reports require a cached base-denomi
- unmapped_in_scope_message("open order", instrument_id, Some(
- unmapped_in_scope_message("position", instrument_id, None, c
- Unsupported `TimeInForce` for Polymarket: {value:?}
- Unsupported `TimeInForce` for Polymarket market order: {valu
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a86c2a6711faca03.
Report an issue: GitHub.