nautechsystems/nautilus_trader · error
invalid Bybit TP/SL order type: '{s}', expected Market or Li
Error message
invalid Bybit TP/SL order type: '{s}', expected Market or Limit What it means
When parsing Bybit TP/SL parameters, the adapter maps the order type attached to TP/SL orders to BybitOrderType. Only "Market" and "Limit" are defined by Bybit for TP/SL orders; any other string is rejected explicitly instead of falling through serde's lenient deserialization.
Source
Thrown at crates/adapters/bybit/src/common/parse.rs:1969
Ok(result)
}
pub(crate) fn parse_trigger_type(s: &str) -> anyhow::Result<BybitTriggerType> {
match s {
"LastPrice" => Ok(BybitTriggerType::LastPrice),
"MarkPrice" => Ok(BybitTriggerType::MarkPrice),
"IndexPrice" => Ok(BybitTriggerType::IndexPrice),
_ => anyhow::bail!(
"invalid Bybit trigger type: '{s}', expected LastPrice, MarkPrice, or IndexPrice"
),
}
}
pub(crate) fn parse_tp_sl_order_type(s: &str) -> anyhow::Result<BybitOrderType> {
match s {
"Market" => Ok(BybitOrderType::Market),
"Limit" => Ok(BybitOrderType::Limit),
_ => anyhow::bail!("invalid Bybit TP/SL order type: '{s}', expected Market or Limit"),
}
}
// A plain `serde_json` deserialize would accept unknown strings: `BybitTpSlMode` carries a
// `#[serde(other)] Unknown` variant, so garbage would silently map to `Unknown`.
pub(crate) fn parse_tpsl_mode(s: &str) -> anyhow::Result<BybitTpSlMode> {
match s {
"Full" => Ok(BybitTpSlMode::Full),
"Partial" => Ok(BybitTpSlMode::Partial),
_ => anyhow::bail!("invalid Bybit TP/SL mode: '{s}', expected Full or Partial"),
}
}
#[cfg(test)]
mod tests {
use nautilus_model::{
data::BarSpecification,
enums::{AggregationSource, BarAggregation, PositionSide, PriceType},View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the raw response's orderType field and correct it to "Market" or "Limit"
- Update the adapter/dependency to a version supporting the new order type
- Fix fixture or mock data casing to match Bybit's exact strings
Example fix
// before
parse_tp_sl_order_type("market")? // rejected
// after
parse_tp_sl_order_type("Market")? Defensive patterns
Strategy: validation
Validate before calling
fn is_valid_tpsl_order_type(s: &str) -> bool { matches!(s, "Market" | "Limit") } Type guard
fn valid_order_type(s: &str) -> Option<BybitOrderType> {
match s { "Market" => Some(BybitOrderType::Market), "Limit" => Some(BybitOrderType::Limit), _ => None }
} Try / catch
let ot = parse_tp_sl_order_type(raw).unwrap_or(BybitOrderType::Market); // or surface the error
Prevention
- Only construct TP/SL payloads from the adapter's typed enums
- Fix fixtures to exact Bybit strings ("Market"/"Limit")
- Track Bybit API changelogs for new order types
When it happens
Trigger: parse_bybit_tp_sl_params receives a payload where the TP/SL order type field (e.g. orderType in the TPSL response) is not exactly "Market" or "Limit" — typos, lowercase 'market', or an exchange-side new value.
Common situations: Mock/test fixtures with wrong casing; a newer Bybit API adding an order type the adapter doesn't know; manually constructed JSON used in integration testing.
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
- invalid Bybit trigger type: '{s}', expected LastPrice, MarkP
- invalid Bybit TP/SL mode: '{s}', expected Full or Partial
- invalid Bybit bbo_side_type: '{s}', expected Queue or Counte
- invalid 'bbo_level': '{s}', expected 1, 2, 3, 4, or 5
- invalid 'take_profit' price: '{s}', expected a non-negative
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/db720bce7dba5d1d.
Report an issue: GitHub.