{"record":{"id":"126791d85e0f6810","repo":"nautechsystems/nautilus_trader","slug":"base-coin-is-empty-for-symbol","errorCode":null,"errorMessage":"base_coin is empty for symbol '{}'","messagePattern":"base_coin is empty for symbol '(.+?)'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/common/parse.rs","lineNumber":433,"sourceCode":"        .build()\n        .unwrap();\n\n    Ok(InstrumentAny::CurrencyPair(instrument))\n}\n\n/// Parses a linear contract definition (perpetual or dated future) into a Nautilus instrument.\n///\n/// # Panics\n///\n/// Panics if the constructed instrument fails validation.\npub fn parse_linear_instrument(\n    definition: &BybitInstrumentLinear,\n    fee_rate: &BybitFeeRate,\n    ts_event: UnixNanos,\n    ts_init: UnixNanos,\n) -> anyhow::Result<InstrumentAny> {\n    // Validate required fields\n    anyhow::ensure!(\n        !definition.base_coin.is_empty(),\n        \"base_coin is empty for symbol '{}'\",\n        definition.symbol\n    );\n    anyhow::ensure!(\n        !definition.quote_coin.is_empty(),\n        \"quote_coin is empty for symbol '{}'\",\n        definition.symbol\n    );\n\n    let base_currency = get_currency(definition.base_coin.as_str());\n    let quote_currency = get_currency(definition.quote_coin.as_str());\n    let settlement_currency = resolve_settlement_currency(\n        definition.settle_coin.as_str(),\n        base_currency,\n        quote_currency,\n    )?;\n","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/common/parse.rs#L415-L451","documentation":"When building a NautilusTrader instrument from a Bybit linear (USDT/USDC-margined) instrument definition, the parser requires base_coin to be a nonempty string because it is used to derive the base Currency of the instrument. An empty base_coin means the exchange payload is incomplete or malformed, so parse_linear_instrument fails fast with this anyhow::ensure! error including the symbol.","triggerScenarios":"Calling parse_linear_instrument (or its callers: linear_instrument, request_instruments, position parsing) with a BybitInstrumentLinear whose base_coin field is empty — typically from a truncated or missing field in the exchange /v5/market/instruments-info response or a hand-constructed definition.","commonSituations":"Bybit API returning partial instrument data for newly listed or delisted symbols; deserialization defaults leaving base_coin empty when the JSON key is missing; test fixtures with stub instruments missing coin fields.","solutions":["Check the Bybit instruments-info response for the symbol and confirm base_coin is populated","Fix the deserialization/fixture so base_coin is mapped correctly from the API field","Filter out instruments with empty base_coin before calling parse_linear_instrument","Report/refresh stale cached instrument definitions that lack the coin fields"],"exampleFix":"// before\nlet inst = parse_linear_instrument(&BybitInstrumentLinear { symbol: \"BTCUSDT\".into(), base_coin: \"\".into(), ..def }, &fee, ts_event, ts_init)?;\n// after\nif def.base_coin.is_empty() {\n    tracing::warn!(symbol = %def.symbol, \"skipping instrument with empty base_coin\");\n    return Ok(None);\n}\nlet inst = parse_linear_instrument(&def, &fee, ts_event, ts_init)?;","handlingStrategy":"validation","validationCode":"fn linear_definition_is_complete(def: &BybitInstrumentLinear) -> bool {\n    !def.base_coin.is_empty() && !def.quote_coin.is_empty()\n}","typeGuard":"fn has_base_coin(def: &BybitInstrumentLinear) -> bool {\n    !def.base_coin.trim().is_empty()\n}","tryCatchPattern":"match parse_linear_instrument(&def, &fee, ts_event, ts_init) {\n    Ok(inst) => instruments.push(inst),\n    Err(e) => { tracing::warn!(symbol = %def.symbol, \"skipping instrument: {e:#}\"); continue; }\n}","preventionTips":["Validate exchange payloads for required coin fields before parsing","Skip-and-log incomplete instruments instead of failing the whole instruments request","Check deserialization does not silently default missing JSON keys to empty strings","Keep test fixtures aligned with real API responses"],"tags":["bybit","instrument-parsing","validation"],"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"}