nautechsystems/nautilus_trader · error · anyhow::Error
base_coin is empty for symbol '{}'
Error message
base_coin is empty for symbol '{}' What it means
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.
Source
Thrown at crates/adapters/bybit/src/common/parse.rs:433
.build()
.unwrap();
Ok(InstrumentAny::CurrencyPair(instrument))
}
/// Parses a linear contract definition (perpetual or dated future) into a Nautilus instrument.
///
/// # Panics
///
/// Panics if the constructed instrument fails validation.
pub fn parse_linear_instrument(
definition: &BybitInstrumentLinear,
fee_rate: &BybitFeeRate,
ts_event: UnixNanos,
ts_init: UnixNanos,
) -> anyhow::Result<InstrumentAny> {
// Validate required fields
anyhow::ensure!(
!definition.base_coin.is_empty(),
"base_coin is empty for symbol '{}'",
definition.symbol
);
anyhow::ensure!(
!definition.quote_coin.is_empty(),
"quote_coin is empty for symbol '{}'",
definition.symbol
);
let base_currency = get_currency(definition.base_coin.as_str());
let quote_currency = get_currency(definition.quote_coin.as_str());
let settlement_currency = resolve_settlement_currency(
definition.settle_coin.as_str(),
base_currency,
quote_currency,
)?;
View on GitHub (pinned to 18893faf8b)
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
Example fix
// before
let inst = parse_linear_instrument(&BybitInstrumentLinear { symbol: "BTCUSDT".into(), base_coin: "".into(), ..def }, &fee, ts_event, ts_init)?;
// after
if def.base_coin.is_empty() {
tracing::warn!(symbol = %def.symbol, "skipping instrument with empty base_coin");
return Ok(None);
}
let inst = parse_linear_instrument(&def, &fee, ts_event, ts_init)?; Defensive patterns
Strategy: validation
Validate before calling
fn linear_definition_is_complete(def: &BybitInstrumentLinear) -> bool {
!def.base_coin.is_empty() && !def.quote_coin.is_empty()
} Type guard
fn has_base_coin(def: &BybitInstrumentLinear) -> bool {
!def.base_coin.trim().is_empty()
} Try / catch
match parse_linear_instrument(&def, &fee, ts_event, ts_init) {
Ok(inst) => instruments.push(inst),
Err(e) => { tracing::warn!(symbol = %def.symbol, "skipping instrument: {e:#}"); continue; }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- quote_coin is empty for symbol '{}'
- Invalid tickSize of 0 for symbol '{}', cannot create instrum
- invalid 'bbo_level': '{s}', expected 1, 2, 3, 4, or 5
- invalid 'take_profit' price: '{s}', expected a non-negative
- invalid 'stop_loss' price: '{s}', expected a non-negative va
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/126791d85e0f6810.
Report an issue: GitHub.