{"record":{"id":"415a4ce2cfe0dc65","repo":"nautechsystems/nautilus_trader","slug":"failed-to-build-bybitsetleverageparams","errorCode":null,"errorMessage":"Failed to build BybitSetLeverageParams","messagePattern":"Failed to build BybitSetLeverageParams","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/http/client.rs","lineNumber":1271,"sourceCode":"    /// Panics if required parameters are not provided (should not happen with current implementation).\n    ///\n    /// # References\n    ///\n    /// - <https://bybit-exchange.github.io/docs/v5/position/leverage>\n    pub async fn set_leverage(\n        &self,\n        product_type: BybitProductType,\n        symbol: &str,\n        buy_leverage: &str,\n        sell_leverage: &str,\n    ) -> Result<BybitSetLeverageResponse, BybitHttpError> {\n        let params = BybitSetLeverageParamsBuilder::default()\n            .category(product_type)\n            .symbol(symbol.to_string())\n            .buy_leverage(buy_leverage.to_string())\n            .sell_leverage(sell_leverage.to_string())\n            .build()\n            .expect(\"Failed to build BybitSetLeverageParams\");\n\n        let body = serde_json::to_vec(&params)?;\n        self.send_request::<_, ()>(\n            Method::POST,\n            \"/v5/position/set-leverage\",\n            None,\n            Some(body),\n            true,\n        )\n        .await\n    }\n\n    /// Switches position mode for a product type.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if:\n    /// - Credentials are missing.","sourceCodeStart":1253,"sourceCodeEnd":1289,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/http/client.rs#L1253-L1289","documentation":"`set_leverage` builds `BybitSetLeverageParams` via derive_builder and panics through `expect` if `build()` fails, i.e. if a required field without a default is missing. The chain sets category, symbol, buy_leverage and sell_leverage; any remaining required field unset causes the panic.","triggerScenarios":"A newly added required field on `BybitSetLeverageParams` (e.g. a Bybit V5 API addition like `borrow_mode`) not set by this builder chain, so `build()` returns `Err` and the `expect` fires.","commonSituations":"Crate upgrade after Bybit adds a mandatory leverage parameter; constructing the builder manually and omitting a required setter.","solutions":["Inspect `BybitSetLeverageParams` for non-optional fields and add the missing setter to the chain","After a crate upgrade, rebuild and address any newly required builder fields","Convert the `expect` to `?`/error mapping for graceful failure","Report a bug if it panics via the public `set_leverage` path"],"exampleFix":"// before\n.build().expect(\"Failed to build BybitSetLeverageParams\");\n// after\n.build().map_err(BybitHttpError::InvalidParams)?;","handlingStrategy":"validation","validationCode":"// Validate leverage strings are numeric and within Bybit limits before calling\nlet b: f64 = buy_leverage.parse()?; let s: f64 = sell_leverage.parse()?;\nassert!((1.0..=100.0).contains(&b) && (1.0..=100.0).contains(&s), \"leverage out of range\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = client.set_leverage(cat, sym, buy, sell).await { log::error!(\"set_leverage failed: {e}\"); return Err(e.into()); }","preventionTips":["Format leverage as strings like \"10\" matching Bybit step rules","Ensure buy/sell leverage are equal unless using Bybit cross-margin semantics","Re-check builder field requirements after dependency upgrades"],"tags":["panic","builder","leverage","bybit"],"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"}