nautechsystems/nautilus_trader · error

Unspecified Bybit order side

Error message

Unspecified Bybit order side

What it means

The `TryFrom<BybitOrderSide>` impl for the domain `OrderSide` rejects `BybitOrderSide::Unknown` with this error, because a side that Bybit did not map to Buy/Sell cannot be converted into a domain order side. It prevents silently treating an unspecified/unknown exchange side as a real direction.

Source

Thrown at crates/adapters/bybit/src/common/enums.rs:653

impl From<BybitOrderSide> for Option<OrderSide> {
    fn from(value: BybitOrderSide) -> Self {
        match value {
            BybitOrderSide::Buy => Some(OrderSide::Buy),
            BybitOrderSide::Sell => Some(OrderSide::Sell),
            BybitOrderSide::Unknown => None,
        }
    }
}

impl TryFrom<BybitOrderSide> for OrderSide {
    type Error = anyhow::Error;

    fn try_from(value: BybitOrderSide) -> Result<Self, Self::Error> {
        match value {
            BybitOrderSide::Buy => Ok(Self::Buy),
            BybitOrderSide::Sell => Ok(Self::Sell),
            BybitOrderSide::Unknown => anyhow::bail!("Unspecified Bybit order side"),
        }
    }
}

impl From<OrderSide> for BybitOrderSide {
    fn from(value: OrderSide) -> Self {
        match value {
            OrderSide::Buy => Self::Buy,
            OrderSide::Sell => Self::Sell,
        }
    }
}

impl From<BybitTriggerType> for TriggerType {
    fn from(value: BybitTriggerType) -> Self {
        match value {
            BybitTriggerType::None => Self::Default,
            BybitTriggerType::LastPrice => Self::LastPrice,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the raw Bybit payload's side field and fix the mapping for the new/empty value.
  2. Update the adapter to a version that recognizes the side string Bybit is sending (API version change).
  3. Guard the conversion: only convert when `side != BybitOrderSide::Unknown`, otherwise log and skip.
  4. Check for market-specific quirks (e.g. some instruments report side differently) and normalize upstream.

Example fix

// before
let side: OrderSide = bybit_side.try_into()?;
// after
let side = match bybit_side {
    BybitOrderSide::Unknown => { log::warn!("skipping order with unspecified side"); return Ok(()); }
    s => s.try_into()?,
};
Defensive patterns

Strategy: validation

Validate before calling

fn order_side_is_known(side: &BybitOrderSide) -> bool {
    !matches!(side, BybitOrderSide::Unknown)
}
anyhow::ensure!(order_side_is_known(&bybit_side), "Bybit side missing in payload");

Type guard

fn as_known_side(side: &BybitOrderSide) -> Option<&BybitOrderSide> {
    match side {
        BybitOrderSide::Unknown => None,
        s => Some(s),
    }
}

Try / catch

match OrderSide::try_from(bybit_side) {
    Ok(side) => process(side),
    Err(e) if e.to_string().contains("Unspecified Bybit order side") => {
        warn!("order update without side; skipping");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Converting a Bybit order/notification side to the domain type when the raw payload contained an unrecognized or missing side, yielding `BybitOrderSide::Unknown`.

Common situations: Parsing execution/order updates from Bybit whose `orderSide` field is empty or a newly introduced value; older adapter version not knowing a new side string; conditional-order payloads with absent side.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/191b323b9923ce43. Report an issue: GitHub.