nautechsystems/nautilus_trader · error

invalid Bybit bbo_side_type: '{s}', expected Queue or Counte

Error message

invalid Bybit bbo_side_type: '{s}', expected Queue or Counterparty

What it means

parse_bbo_side_type parses the bbo_side_type parameter controlling best-bid-offer (BBO) trigger behavior for TP/SL orders into the BybitBboSideType enum. Only 'queue' and 'counterparty' (case-insensitive) are valid; anything else raises this anyhow error.

Source

Thrown at crates/adapters/bybit/src/common/parse.rs:1768

///
/// # Errors
///
/// Returns an error for any value outside the four types Bybit accepts on an order.
pub fn deserialize_optional_smp_type<'de, D: serde::Deserializer<'de>>(
    d: D,
) -> Result<Option<BybitOrderSmpType>, D::Error> {
    let Some(value) = Option::<String>::deserialize(d)? else {
        return Ok(None);
    };

    parse_smp_type(&value).map(Some).map_err(D::Error::custom)
}

pub fn parse_bbo_side_type(s: &str) -> anyhow::Result<BybitBboSideType> {
    match s.to_ascii_lowercase().as_str() {
        "queue" => Ok(BybitBboSideType::Queue),
        "counterparty" => Ok(BybitBboSideType::Counterparty),
        _ => anyhow::bail!("invalid Bybit bbo_side_type: '{s}', expected Queue or Counterparty"),
    }
}

pub fn parse_bbo_level(s: String) -> anyhow::Result<String> {
    match s.as_str() {
        "1" | "2" | "3" | "4" | "5" => Ok(s),
        _ => anyhow::bail!("invalid 'bbo_level': '{s}', expected 1, 2, 3, 4, or 5"),
    }
}

/// Parses Bybit TP/SL parameters from an optional params map.
pub fn parse_bybit_tp_sl_params(params: Option<&Params>) -> anyhow::Result<BybitTpSlParams> {
    let Some(params) = params else {
        return Ok(BybitTpSlParams::default());
    };

    let mut result = BybitTpSlParams {
        is_leverage: params.get_bool("is_leverage").unwrap_or(false),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set bbo_side_type to exactly 'Queue' or 'Counterparty' (case-insensitive)
  2. Remove bbo_side_type entirely to use the default instead of an invalid value
  3. Check you are not confusing it with trigger_by values (LastPrice, MarkPrice, IndexPrice)

Example fix

// before
params.insert("bbo_side_type", "LAST_PRICE");
// after
params.insert("bbo_side_type", "Queue");
Defensive patterns

Strategy: validation

Validate before calling

assert bbo_side_type.lower() in ("queue", "counterparty"), f"invalid bbo_side_type: {bbo_side_type}"

Type guard

fn is_valid_bbo_side_type(s: &str) -> bool {
    matches!(s.to_ascii_lowercase().as_str(), "queue" | "counterparty")
}

Try / catch

match parse_bbo_side_type(s) {
    Ok(t) => use(t),
    Err(e) => { log::error!("{e}"); omit_bbo_side_type() }
}

Prevention

When it happens

Trigger: Submitting an order via py_submit_order or calling parse_bybit_tp_sl_params with params containing bbo_side_type set to something other than queue/counterparty, e.g. 'last_price' or 'mark'.

Common situations: Copying bbo_side_type values from Bybit UI docs for other trigger types, or confusing this option with the trigger_by parameter which uses different values.

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/0e0aff7915f6b76a. Report an issue: GitHub.