{"record":{"id":"fa473739f9c439db","repo":"nautechsystems/nautilus_trader","slug":"lighter-client-order-index-probe-exhausted-after","errorCode":null,"errorMessage":"Lighter client_order_index probe exhausted after {} attempts for cloid {cloid}","messagePattern":"Lighter client_order_index probe exhausted after (.+?) attempts for cloid (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/lighter/src/websocket/dispatch.rs","lineNumber":1278,"sourceCode":"                    entry.insert(cloid);\n\n                    if attempt > 0 {\n                        log::warn!(\n                            \"Lighter client_order_index collision at {index}: \\\n                             cloid {cloid} re-derived to {candidate} after {attempt} probe(s)\",\n                        );\n                    }\n                    return Ok(candidate);\n                }\n                dashmap::mapref::entry::Entry::Occupied(entry) => {\n                    if *entry.get() == cloid {\n                        return Ok(candidate);\n                    }\n                    candidate = next_probe_index(candidate);\n                }\n            }\n        }\n        anyhow::bail!(\n            \"Lighter client_order_index probe exhausted after {} attempts for cloid {cloid}\",\n            CLOID_INDEX_PROBE_LIMIT + 1,\n        )\n    }\n\n    /// Restore an exact order identity observed during reconciliation.\n    ///\n    /// `terminal` reflects the current venue report because the cached order can be stale after a\n    /// restart.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error when the cached order does not carry the same venue order ID, the client\n    /// index is outside the venue-safe range, or the binding conflicts with existing local state.\n    pub(crate) fn restore_reconciled_order(\n        &self,\n        order: &OrderAny,\n        client_order_index: i64,","sourceCodeStart":1260,"sourceCodeEnd":1296,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/lighter/src/websocket/dispatch.rs#L1260-L1296","documentation":"Raised when resolving a unique client_order_index for a cloid fails after exhausting the probe limit. The dispatcher probes candidate indices (skipping ones already bound to other cloids) up to CLOID_INDEX_PROBE_LIMIT + 1 attempts; if every candidate collides, it bails with this message.","triggerScenarios":"Submitting an order with a cloid when the local client_order_index space for the account is saturated with bindings — every probed index is already claimed by an active or recorded order, so no free candidate is found within the limit.","commonSituations":"Long-running sessions accumulating thousands of live order bindings; a reconciliation bug leaving stale bindings in the index map; reusing the same account across multiple adapter instances that each bind indices independently; an internal map not being cleaned up after cancels.","solutions":["Cancel stale open orders and allow reconciliation to prune bindings, freeing probe space.","Ensure only one adapter instance owns order submission for the account; multiple instances race for the same index space.","Restart the data/execution client to rebuild the binding map from exchange state.","Check for a leak where bindings aren't removed after fills/cancels; report/patch the cleanup path.","Increase CLOID_INDEX_PROBE_LIMIT if legitimately high order throughput needs more candidates."],"exampleFix":"// before: many stale bindings exhaust probes\nanyhow::bail!(\"probe exhausted after {} attempts for cloid {cloid}\", LIMIT + 1);\n\n// after: prune dead bindings before probing\ncleanup_resolved_bindings(&self.index_map);\nlet idx = self.probe_free_index(cloid)?;","handlingStrategy":"validation","validationCode":"// before submitting, ensure a single writer owns the index space\nassert!(submission_lock.is_held_by_current_task());","typeGuard":null,"tryCatchPattern":"match resolve_client_order_index(cloid).await {\n    Err(e) if e.to_string().contains(\"probe exhausted\") => {\n        log::error!(\"index space saturated: {e:#}\");\n        // trigger reconciliation/restart to rebuild bindings\n    }\n    r => r?,\n}","preventionTips":["Run only one adapter instance per trading account","Cancel stale orders so bindings get pruned","Watch for binding-map leaks after fills/cancels","Restart clients periodically in very long-running sessions"],"tags":["orders","state-management","rust","adapter"],"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"}