{"record":{"id":"38510c9635888e1f","repo":"nautechsystems/nautilus_trader","slug":"instrumentid-symbol-is-empty","errorCode":null,"errorMessage":"InstrumentId symbol is empty","messagePattern":"InstrumentId symbol is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/http/client.rs","lineNumber":4725,"sourceCode":"                    );\n                };\n                return self\n                    .generate_spot_position_reports_from_wallet(account_id, instrument_id)\n                    .await;\n            } else {\n                // Return empty vector when SPOT position reports are disabled\n                return Ok(Vec::new());\n            }\n        }\n\n        let ts_init = self.generate_ts_init();\n        let mut reports = Vec::new();\n\n        // Build query parameters based on whether a specific instrument is requested\n        let symbol = if let Some(id) = instrument_id {\n            let symbol_str = id.symbol.as_str();\n            if symbol_str.is_empty() {\n                anyhow::bail!(\"InstrumentId symbol is empty\");\n            }\n            let bybit_symbol = BybitSymbol::new(symbol_str)?;\n            Some(bybit_symbol.raw_symbol().to_string())\n        } else {\n            None\n        };\n\n        // For LINEAR category, the API requires either symbol OR settleCoin\n        // When querying all positions (no symbol), we must iterate through settle coins\n        if product_type == BybitProductType::Linear && symbol.is_none() {\n            // Query positions for each known settle coin with pagination\n            for settle_coin in [\"USDT\", \"USDC\"] {\n                let mut cursor: Option<String> = None;\n\n                loop {\n                    let params = BybitPositionListParams {\n                        category: product_type,\n                        symbol: None,","sourceCodeStart":4707,"sourceCodeEnd":4743,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/http/client.rs#L4707-L4743","documentation":"When converting an InstrumentId to a Bybit symbol, the adapter checks that the symbol component is non-empty. An InstrumentId with an empty symbol cannot map to a venue symbol, so the request is aborted.","triggerScenarios":"Passing an InstrumentId whose symbol part is an empty string (e.g. parsed from \"@BYBIT.SPOT\"-style or malformed input) into an instruments/positions query that expects Some(instrument_id).","commonSituations":"Programmatically constructed InstrumentIds where the symbol was built from an empty or untrimmed string; parsing venue metadata that returned blank symbols.","solutions":["Validate the symbol is non-empty before constructing the InstrumentId","Trim and normalize venue symbols when building InstrumentIds","Pass None instead of an empty-symbol InstrumentId when no specific instrument is intended"],"exampleFix":"// before\nlet id = InstrumentId::from(format!(\"@{}\", venue).as_str()); // empty symbol\n// after\nanyhow::ensure!(!symbol.is_empty(), \"symbol required\");\nlet id = InstrumentId::from(format!(\"{symbol}@{venue\").as_str());","handlingStrategy":"validation","validationCode":"anyhow::ensure!(!instrument_id.symbol.as_str().is_empty(), \"instrument symbol must be non-empty\");\nlet bybit_symbol = BybitSymbol::new(instrument_id.symbol.as_str())?;","typeGuard":"fn has_symbol(id: &InstrumentId) -> bool { !id.symbol.as_str().is_empty() }","tryCatchPattern":null,"preventionTips":["Validate symbols when constructing InstrumentIds","Trim venue metadata before symbol construction","Pass None rather than an empty-symbol ID when the instrument is unknown"],"tags":["bybit","instrument-id","empty-symbol"],"backgroundTag":"empty-required-field","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"}