{"record":{"id":"8236213460d82598","repo":"nautechsystems/nautilus_trader","slug":"batch-submit-orders-failed","errorCode":null,"errorMessage":"batch submit orders failed","messagePattern":"batch submit orders failed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/execution.rs","lineNumber":2402,"sourceCode":"                            dispatch_state.order_identities.remove(cid);\n                            emitter.emit_order_rejected_event(\n                                strategy_id,\n                                instrument_id,\n                                *cid,\n                                &reason,\n                                ts_event,\n                                false,\n                            );\n                        }\n                    }\n                    CommandFailure::Ambiguous(reason) | CommandFailure::VenueRejected(reason) => {\n                        log::warn!(\n                            \"Ambiguous batch submit failure for {} orders on {instrument_id}, awaiting reconciliation: {reason}\",\n                            client_order_ids.len()\n                        );\n                    }\n                }\n                return Err(anyhow::Error::new(e).context(\"batch submit orders failed\"));\n            }\n\n            Ok(())\n        });\n\n        Ok(())\n    }\n\n    fn modify_order(&self, cmd: ModifyOrder) -> anyhow::Result<()> {\n        if is_spread_instrument(cmd.instrument_id) {\n            self.emitter.emit_order_modify_rejected_event(\n                cmd.strategy_id,\n                cmd.instrument_id,\n                cmd.client_order_id,\n                cmd.venue_order_id,\n                \"OKX spread orders do not support modify requests\",\n                self.clock.get_time_ns(),\n            );","sourceCodeStart":2384,"sourceCodeEnd":2420,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/execution.rs#L2384-L2420","documentation":"Submitting a batch (order list) of regular orders over the OKX private WebSocket failed. ws_private.batch_submit_orders returned Err; the adapter first emits OrderRejected events for every leg when the failure is NotSent (definitely never reached OKX), or logs an 'Ambiguous batch submit failure' warning for Ambiguous/VenueRejected outcomes, then returns the error with this context.","triggerScenarios":"submit_order_list on a non-spread instrument; ws_private.batch_submit_orders returned Err: WS disconnected (NotSent), ack timeout leaving success unknown (Ambiguous), or OKX rejecting the batch message (VenueRejected).","commonSituations":"Submitting multi-leg lists during WS reconnects; per-leg parameter rejections (bad price/size/post-only flags) surfacing as batch errors; sending lists larger than OKX WS batch limits; ambiguous outcomes requiring reconciliation to determine what actually landed.","solutions":["Check the classified failure: if NotSent, all legs were rejected locally and can be safely resubmitted after fixing the cause.","If Ambiguous/VenueRejected, wait for/run reconciliation before resubmitting — orders may have been placed, and blind resubmission can double position.","Validate every leg with the same rules OKX enforces (price/quantity precision, post-only, trade mode) before submit_order_list.","Ensure the private WS session is connected and authenticated; retry after reconnect if it was down."],"exampleFix":"// before: resubmitting immediately after an ambiguous failure\ntrader.submit_order_list(cmd);\n// after: reconcile first when outcome is unknown\nmatch failure {\n    CommandFailure::NotSent(_) => trader.submit_order_list(cmd),\n    CommandFailure::Ambiguous(_) | CommandFailure::VenueRejected(_) => {\n        trader.reconcile_state(instrs).await; // then decide per-leg\n    }\n}","handlingStrategy":"retry","validationCode":"// Validate every leg before submitting the list atomically\nfor order in orders.iter() {\n    validate_order(order, trade_mode, OrderSubmission::List)\n        .expect(\"leg invalid; list would be denied\");\n}","typeGuard":null,"tryCatchPattern":"// Distinguish NotSent (safe to resend) from Ambiguous (reconcile first)\nif let Err(e) = trader.submit_order_list(cmd) {\n    match classify_okx_ws_failure(&e) {\n        CommandFailure::NotSent(_) => retry_list(cmd),\n        CommandFailure::Ambiguous(_) | CommandFailure::VenueRejected(_) => {\n            reconcile_before_resubmit();\n        }\n    }\n}","preventionTips":["Never blind-resubmit a list after an Ambiguous failure — orders may be live.","Pre-validate all legs so one bad leg does not poison the batch.","Keep batch sizes within OKX WS message limits.","Ensure WS private is connected and authenticated before list submissions."],"tags":["okx","websocket","batch-orders","order-submission","reconciliation"],"backgroundTag":"network-request-failed","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"}