nautechsystems/nautilus_trader · error
retired Lighter binding conflicts at client_order_index {cli
Error message
retired Lighter binding conflicts at client_order_index {client_order_index} and venue order ID {venue_order_id} What it means
When binding a brand-new (previously unseen cloid) terminal order, the code ensures no retired order is already bound to the same (client_order_index, venue_order_id) pair. A hit means two different cloids claim the same venue-side identity in the retired map — a hard conflict the adapter refuses to create.
Source
Thrown at crates/adapters/lighter/src/websocket/dispatch.rs:1342
self.mark_triggered_emitted(cloid);
}
return Ok(());
}
if let Some(existing) = self.retired_orders.identity_for_cloid(&cloid) {
anyhow::ensure!(
terminal
&& existing.client_order_index == client_order_index
&& existing.matches_venue_order_id(venue_order_id),
"retired Lighter order {cloid} conflicts with reconciliation binding",
);
return Ok(());
}
let identity = OrderIdentity::restored(order, client_order_index, venue_order_id);
if terminal {
anyhow::ensure!(
self.retired_orders
.cloid_for_venue(client_order_index, venue_order_id)
.is_none(),
"retired Lighter binding conflicts at client_order_index {client_order_index} and venue order ID {venue_order_id}",
);
self.retired_orders.insert(cloid, identity);
} else {
if let Some(existing) = self.venue_id_map.get(&cloid) {
anyhow::ensure!(
*existing.value() == venue_order_id,
"active Lighter order {cloid} conflicts with venue order ID {venue_order_id}",
);
}
match self.cloid_map.entry(client_order_index) {
dashmap::mapref::entry::Entry::Vacant(entry) => {
self.venue_id_map.insert(cloid, venue_order_id);
self.order_identities.insert(cloid, identity);View on GitHub (pinned to 18893faf8b)
Solutions
- Regenerate client order IDs so cloid↔client_order_index mapping is injective per session
- Clear retired_orders and rebuild from authoritative venue state
- Audit persisted order cache for duplicate (index, venue_id) pairs
Defensive patterns
Strategy: validation
Validate before calling
if retired.cloid_for_venue(idx, vid).is_some() {
tracing::error!("venue identity {idx}/{vid} already bound to another cloid");
full_reconcile_from_venue().await?;
} Try / catch
if let Err(e) = bind_reconciliation(order, idx, vid, terminal).await {
if e.to_string().contains("retired Lighter binding conflicts") {
rebuild_retired_map_from_venue().await?;
return Ok(());
}
return Err(e);
} Prevention
- Ensure client_order_index is unique per cloid (injective mapping)
- Audit persisted order caches for duplicate venue identities
- Rebuild retired maps from venue state rather than trusting cross-session persistence
When it happens
Trigger: A terminal reconciliation event whose cloid is new but whose client_order_index + venue_order_id combination is already occupied by a different cloid in retired_orders.
Common situations: Client_order_id collisions across restarts (same index reused with different cloids), venue reusing order IDs, corrupted persisted state.
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
- active Lighter order {cloid} conflicts with reconciliation b
- retired Lighter order {cloid} conflicts with reconciliation
- active Lighter order {cloid} conflicts with venue order ID {
- cached Lighter order {cloid} does not match venue order ID {
- Replacement hash {transaction_hash} conflicts with another i
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8c3a9f48e0f195ad.
Report an issue: GitHub.