nautechsystems/nautilus_trader · error

retired Lighter order {cloid} conflicts with reconciliation

Error message

retired Lighter order {cloid} conflicts with reconciliation binding

What it means

If the cloid is already recorded in retired_orders, the new binding is only acceptable when the event is terminal and both client_order_index and venue order ID match the stored identity. Any other combination — e.g. a non-terminal update for an already-retired order, or mismatched identity — trips this ensure!.

Source

Thrown at crates/adapters/lighter/src/websocket/dispatch.rs:1330

            .get(&cloid)
            .map(|entry| entry.value().clone())
        {
            anyhow::ensure!(
                existing.client_order_index == client_order_index
                    && existing.matches_venue_order_id(venue_order_id),
                "active Lighter order {cloid} conflicts with reconciliation binding",
            );

            if terminal {
                self.retire_order_identity(&cloid);
            } else if order.is_triggered() == Some(true) {
                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);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check for late/duplicate events and drop them before reconciliation
  2. Re-reconcile the order's true state from the venue API
  3. Ensure persistence restore writes correct client_order_index and venue_order_id
Defensive patterns

Strategy: validation

Validate before calling

if retired.identity_for_cloid(&cloid).is_some() && !terminal {
    tracing::warn!("ignoring non-terminal event for retired order {cloid}");
    return Ok(());
}

Try / catch

if let Err(e) = bind_reconciliation(order, idx, vid, terminal).await {
    if e.to_string().contains("retired Lighter order") {
        tracing::warn!("stale/duplicate event for retired order; ignoring: {e}");
        return Ok(());
    }
    return Err(e);
}

Prevention

When it happens

Trigger: A non-terminal (open/amend) venue event arrives for a cloid already retired, or a terminal event for a retired cloid carrying a different client_order_index/venue_order_id.

Common situations: Duplicate/delayed events after terminal fill, event replays, cache restored from persistence with stale identities.

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/0ecefa44252607e5. Report an issue: GitHub.