nautechsystems/nautilus_trader · error
invalid Bybit trigger type: '{s}', expected LastPrice, MarkP
Error message
invalid Bybit trigger type: '{s}', expected LastPrice, MarkPrice, or IndexPrice What it means
The Bybit adapter validates the trigger price type reported by Bybit when parsing TP/SL (take-profit/stop-loss) parameters from an exchange response. Bybit only defines three trigger types — LastPrice, MarkPrice, IndexPrice — and any other string means an unrecognized/changed exchange payload. The adapter fails fast rather than guessing, so invalid data cannot silently corrupt order state.
Source
Thrown at crates/adapters/bybit/src/common/parse.rs:1959
} else if let Some(i) = value.as_i64() {
i.to_string()
} else if let Some(u) = value.as_u64() {
u.to_string()
} else {
anyhow::bail!("invalid type for 'bbo_level': {value}, expected string or integer");
};
result.bbo_level = Some(parse_bbo_level(level)?);
}
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),View on GitHub (pinned to 18893faf8b)
Solutions
- Check the raw Bybit payload and confirm the triggerBy value it actually contains
- Upgrade the nautilus Bybit adapter to a version that maps the new trigger type
- Normalize/mutate the value to one of the three supported strings before feeding parse_bybit_tp_sl_params
- If the value is legitimately new, extend the match in parse_trigger_type and open/track an adapter update
Example fix
// before
let tt = parse_trigger_type("last_price")?; // fails
// after
let tt = parse_trigger_type("LastPrice")?; // exact Bybit casing Defensive patterns
Strategy: validation
Validate before calling
const TRIGGER_TYPES: [&str; 3] = ["LastPrice", "MarkPrice", "IndexPrice"];
fn is_valid_trigger(s: &str) -> bool { TRIGGER_TYPES.contains(&s) } Type guard
fn valid_trigger(s: &str) -> Option<BybitTriggerType> {
match s {
"LastPrice" => Some(BybitTriggerType::LastPrice),
"MarkPrice" => Some(BybitTriggerType::MarkPrice),
"IndexPrice" => Some(BybitTriggerType::IndexPrice),
_ => None,
}
} Try / catch
match parse_trigger_type(raw) {
Ok(tt) => proceed(tt),
Err(e) => { log::warn!("unsupported trigger type, skipping TPSL params: {e}"); fallback(); }
} Prevention
- Use the adapter's enum types end-to-end instead of hand-building Bybit JSON strings
- Keep the adapter updated when Bybit adds new triggerBy values
- Match Bybit's exact casing in test fixtures
When it happens
Trigger: Calling parse_bybit_tp_sl_params on a Bybit API response whose triggerBy / tpOrderType trigger field contains a value other than LastPrice, MarkPrice, or IndexPrice (e.g. a new exchange value, a localized payload, or garbage from a mock).
Common situations: Bybit introduces a new trigger type in a API version not yet supported by this adapter version; unit tests or mocks hand-crafting TPSL JSON with typo'd values like 'last_price'; replaying recorded payloads from a different Bybit product line.
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 TP/SL order type: '{s}', expected Market or Li
- 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/b7d32f4f89ac82a7.
Report an issue: GitHub.