nautechsystems/nautilus_trader · error

ambiguous Lighter active-order lookup for client_order_index

Error message

ambiguous Lighter active-order lookup for client_order_index {}

What it means

When looking up by derived client_order_index (no explicit venue_order_id), the adapter requires exactly one match among the venue's active orders; multiple matches are ambiguous and rejected. Skipped only when the caller supplied an explicit venue_order_index.

Source

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

        //      supplied the matching cloid.
        // Substituting on the derivation match (rather than which path
        // matched first) avoids leaving the venue numeric cloid on the
        // report whenever the supplied cloid is the right one.
        if let Some(cloid) = supplied_cloid
            && let Some(client_index) = target_client_index
            && order.client_order_index == client_index
            && report.client_order_id != Some(cloid)
        {
            report = report.with_client_order_id(cloid);
        }
        Ok(dispatch.preserve_pending_order_status(report))
    };

    let mut active_matches = active.orders.iter().filter(|order| matches_order(order));
    let active_match = active_matches.next();

    if target_venue_index.is_none() {
        anyhow::ensure!(
            active_matches.next().is_none(),
            "ambiguous Lighter active-order lookup for client_order_index {}",
            target_client_index.unwrap_or_default(),
        );
    }

    if let Some(order) = active_match {
        return finalize(order).map(Some);
    }

    if target_venue_index.is_none() {
        return Ok(None);
    }

    // Fall back to inactive orders (filled / canceled). Pagination is followed
    // because a single market can hold more than 200 historical inactive
    // orders for a long-running account.
    let mut cursor: Option<String> = None;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. List venue open orders and cancel the duplicate with the same client_order_index, then re-reconcile.
  2. Ensure each order gets a unique client_order_index (do not reuse client order ids).
  3. Look up by explicit venue_order_id to disambiguate when duplicates are known to exist.

Example fix

// before
lookup_order(client_order_id, None, ...)
// after
lookup_order(client_order_id, Some(&venue_order_id), ...) // explicit voi bypasses the ambiguity check
Defensive patterns

Strategy: validation

Validate before calling

let matches: Vec<_> = active.orders.iter().filter(|o| matches_order(o)).collect();
if matches.len() > 1 { /* use explicit venue_order_id or cancel duplicates */ }

Prevention

When it happens

Trigger: Reconciliation/query by client_order_id where the venue's open-orders list contains two orders with the same client_order_index — typically from a duplicated submission (retry after timeout) that the venue accepted twice.

Common situations: Retried submit paths after ambiguous network failures; missing idempotency on the submit side; duplicate client_order_id reuse across orders.

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