{"record":{"id":"a5caed04d3b784ee","repo":"nautechsystems/nautilus_trader","slug":"invalid-depth-depth-must-be-0-50-or-400","errorCode":null,"errorMessage":"Invalid depth {depth}, must be 0, 50, or 400","messagePattern":"Invalid depth (.+?), must be 0, 50, or 400","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/websocket/client.rs","lineNumber":1430,"sourceCode":"    /// - depth 50: Requires VIP4+, subscribes to `books50-l2-tbt`\n    /// - depth 0 or 400:\n    ///   - VIP5+: subscribes to `books-l2-tbt` (400 depth, fastest)\n    ///   - Below VIP5: subscribes to `books` (standard depth)\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if:\n    /// - Subscription request fails\n    /// - depth is 50 but VIP level is below 4\n    pub async fn subscribe_book_with_depth(\n        &self,\n        instrument_id: InstrumentId,\n        depth: u16,\n    ) -> anyhow::Result<()> {\n        let vip = self.vip_level();\n\n        if !matches!(depth, 0 | 50 | 400) {\n            anyhow::bail!(\"Invalid depth {depth}, must be 0, 50, or 400\");\n        }\n\n        if depth == 50 && vip < OKXVipLevel::Vip4 {\n            anyhow::bail!(\"VIP level {vip} insufficient for 50 depth subscription (requires VIP4)\");\n        }\n\n        let channel = select_book_channel(depth as usize, vip);\n        self.subscribe_inst_id(ws_channel_for_book(channel), instrument_id.symbol.inner())\n            .await?;\n        Ok(())\n    }\n\n    /// Subscribes to best bid/ask quote data for an instrument.\n    ///\n    /// Provides tick-by-tick updates of the best bid and ask prices using the bbo-tbt channel.\n    /// Supports all instrument types: SPOT, MARGIN, SWAP, FUTURES, OPTION.\n    ///\n    /// # Errors","sourceCodeStart":1412,"sourceCodeEnd":1448,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/websocket/client.rs#L1412-L1448","documentation":"OKX order-book depth subscriptions only accept 0 (full book), 50, or 400 levels. subscribe_book validates the requested depth before mapping it to a channel and bails with anyhow if the value is anything else. This prevents building a subscription OKX would reject.","triggerScenarios":"Calling subscribe_book (or the subscribe-book data request path) with a depth other than 0, 50, or 400, e.g. depth=10 or depth=100 in the WebSocket client config or SubscriptionCommand.","commonSituations":"Hardcoding a depth that matches another exchange's tick sizes (Binance 5/10/20), typos in config, or porting code between adapters without adjusting depth values.","solutions":["Change the requested depth to one of the allowed values: 0, 50, or 400","If you need a smaller book, use depth 0 (full) and slice locally, or check the OKX docs for depth channel options","Add config validation at startup so an invalid depth fails fast before connecting"],"exampleFix":"// before\nsubscribe_book(inst, 10).await?;\n// after\nsubscribe_book(inst, 50).await?; // or 0 / 400","handlingStrategy":"validation","validationCode":"const VALID_DEPTHS: [u16; 3] = [0, 50, 400];\nif !VALID_DEPTHS.contains(&depth) {\n    return Err(anyhow::anyhow!(\"depth {depth} not in [0, 50, 400]\"));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Constrain depth via an enum (Depth::Full | Depth::L50 | Depth::L400) instead of a raw u16","Validate depth in config parsing at startup"],"tags":["okx","websocket","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}