{"record":{"id":"afa5f034ca45f5d6","repo":"nautechsystems/nautilus_trader","slug":"ambiguous-lighter-active-order-lookup-for-client-o-afa5f0","errorCode":null,"errorMessage":"ambiguous Lighter active-order lookup for client_order_index {}","messagePattern":"ambiguous Lighter active-order lookup for client_order_index (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/websocket/dispatch.rs","lineNumber":1882,"sourceCode":"        //      supplied the matching cloid.\n        // Substituting on the derivation match (rather than which path\n        // matched first) avoids leaving the venue numeric cloid on the\n        // report whenever the supplied cloid is the right one.\n        if let Some(cloid) = supplied_cloid\n            && let Some(client_index) = target_client_index\n            && order.client_order_index == client_index\n            && report.client_order_id != Some(cloid)\n        {\n            report = report.with_client_order_id(cloid);\n        }\n        Ok(dispatch.preserve_pending_order_status(report))\n    };\n\n    let mut active_matches = active.orders.iter().filter(|order| matches_order(order));\n    let active_match = active_matches.next();\n\n    if target_venue_index.is_none() {\n        anyhow::ensure!(\n            active_matches.next().is_none(),\n            \"ambiguous Lighter active-order lookup for client_order_index {}\",\n            target_client_index.unwrap_or_default(),\n        );\n    }\n\n    if let Some(order) = active_match {\n        return finalize(order).map(Some);\n    }\n\n    if target_venue_index.is_none() {\n        return Ok(None);\n    }\n\n    // Fall back to inactive orders (filled / canceled). Pagination is followed\n    // because a single market can hold more than 200 historical inactive\n    // orders for a long-running account.\n    let mut cursor: Option<String> = None;","sourceCodeStart":1864,"sourceCodeEnd":1900,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/websocket/dispatch.rs#L1864-L1900","documentation":"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.","triggerScenarios":"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.","commonSituations":"Retried submit paths after ambiguous network failures; missing idempotency on the submit side; duplicate client_order_id reuse across orders.","solutions":["List venue open orders and cancel the duplicate with the same client_order_index, then re-reconcile.","Ensure each order gets a unique client_order_index (do not reuse client order ids).","Look up by explicit venue_order_id to disambiguate when duplicates are known to exist."],"exampleFix":"// before\nlookup_order(client_order_id, None, ...)\n// after\nlookup_order(client_order_id, Some(&venue_order_id), ...) // explicit voi bypasses the ambiguity check","handlingStrategy":"validation","validationCode":"let matches: Vec<_> = active.orders.iter().filter(|o| matches_order(o)).collect();\nif matches.len() > 1 { /* use explicit venue_order_id or cancel duplicates */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use unique client_order_index per order","Make submit retries idempotent to avoid venue-side duplicates","Prefer lookups with an explicit venue_order_id"],"tags":["reconciliation","duplicate-order","ambiguity"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}