{"record":{"id":"d304098eefd22c28","repo":"nautechsystems/nautilus_trader","slug":"order-conversion-must-set-a-cloid","errorCode":null,"errorMessage":"order conversion must set a CLOID","messagePattern":"order conversion must set a CLOID","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/execution.rs","lineNumber":2903,"sourceCode":"    staged_brackets: Arc<Mutex<StagedBracketState>>,\n    builder: Option<crate::http::models::HyperliquidExchangeBuilderFee>,\n    clock: &'static AtomicTime,\n    task_spawner: &TaskSpawner,\n) {\n    let (orders, requests): (Vec<_>, Vec<_>) = children\n        .into_iter()\n        .map(|child| (child.order, child.request))\n        .unzip();\n\n    let denied_orders = orders.clone();\n    let task_emitter = emitter.clone();\n    let ws_client = ws_client.clone();\n    let http_client = http_client.clone();\n    let child_spawner = task_spawner.clone();\n\n    if let Err(e) = task_spawner.spawn(async move {\n        for (order, request) in orders.iter().zip(requests.iter()) {\n            let cloid = request.cloid.expect(\"order conversion must set a CLOID\");\n            http_client.cache_client_order_id_cloid(order.client_order_id(), cloid);\n            ws_client.cache_cloid_mapping(Ustr::from(&cloid.to_hex()), order.client_order_id());\n            register_order_context_into(&dispatch_state, order);\n            task_emitter.emit_order_submitted(order);\n        }\n\n        post_order_batch(\n            \"Bracket child batch\",\n            orders,\n            requests,\n            HyperliquidExchangeGrouping::Na,\n            builder,\n            &task_emitter,\n            &ws_client,\n            &http_client,\n            dispatch_state,\n            staged_brackets,\n            clock,","sourceCodeStart":2885,"sourceCodeEnd":2921,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/execution.rs#L2885-L2921","documentation":"When submitting orders over the Hyperliquid websocket, the adapter requires each built `HyperliquidExchangePlaceOrderRequest` to carry a `cloid` (client order ID) so it can cache the client_order_id↔cloid mapping for order tracking and cancels/modifies by CLOID. The conversion from a Nautilus order to an exchange request must always set `cloid`; a `None` means the conversion function skipped it, and downstream ID correlation would silently break, so the code panics.","triggerScenarios":"Submitting a `SubmitOrder` whose conversion into `HyperliquidExchangePlaceOrderRequest` left `cloid: None` — e.g. the order lacks a client_order_id, or the converter was modified/extended (new order type) without assigning the CLOID; the panic then fires in the submit task when zipping orders with requests.","commonSituations":"Adding support for a new Hyperliquid order type or trigger/TPSL orders and the conversion path forgets `cloid`; orders created without client order IDs; a version change in the conversion helpers dropping the cloid assignment.","solutions":["Fix the order-to-request conversion so `cloid: Some(...)` is always populated (derive it from the order's client_order_id via `Cloid::from_client_order_id`).","Ensure every submitted order has a client_order_id assigned before reaching the Hyperliquid execution client.","In the submit loop, convert the expect into an error log + skip (or reject the order) so one malformed order doesn't kill the task.","Add a test asserting every converted request has a Some(cloid) for each supported order type."],"exampleFix":"// before\nlet request = HyperliquidExchangePlaceOrderRequest {\n    // ... fields ...\n    cloid: None, // or omitted\n    ..Default::default()\n};\n// after\nlet cloid = Cloid::from_client_order_id(order.client_order_id());\nlet request = HyperliquidExchangePlaceOrderRequest {\n    // ... fields ...\n    cloid: Some(cloid),\n    ..Default::default()\n};","handlingStrategy":"validation","validationCode":"let Some(cloid) = request.cloid else {\n    tracing::error!(order_id = %order.client_order_id(), \"request missing CLOID\");\n    continue; // or return an error rejecting the order\n};","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always populate cloid in the order-to-request conversion via Cloid::from_client_order_id","Ensure orders carry a client_order_id before submission","Add a property/unit test that every converted request has Some(cloid)"],"tags":["rust","panic","order-submission","cloid","conversion"],"backgroundTag":"missing-required-argument","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"}