{"record":{"id":"b7d32f4f89ac82a7","repo":"nautechsystems/nautilus_trader","slug":"invalid-bybit-trigger-type-s-expected-lastpr","errorCode":null,"errorMessage":"invalid Bybit trigger type: '{s}', expected LastPrice, MarkPrice, or IndexPrice","messagePattern":"invalid Bybit trigger type: '(.+?)', expected LastPrice, MarkPrice, or IndexPrice","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/common/parse.rs","lineNumber":1959,"sourceCode":"        } else if let Some(i) = value.as_i64() {\n            i.to_string()\n        } else if let Some(u) = value.as_u64() {\n            u.to_string()\n        } else {\n            anyhow::bail!(\"invalid type for 'bbo_level': {value}, expected string or integer\");\n        };\n        result.bbo_level = Some(parse_bbo_level(level)?);\n    }\n\n    Ok(result)\n}\n\npub(crate) fn parse_trigger_type(s: &str) -> anyhow::Result<BybitTriggerType> {\n    match s {\n        \"LastPrice\" => Ok(BybitTriggerType::LastPrice),\n        \"MarkPrice\" => Ok(BybitTriggerType::MarkPrice),\n        \"IndexPrice\" => Ok(BybitTriggerType::IndexPrice),\n        _ => anyhow::bail!(\n            \"invalid Bybit trigger type: '{s}', expected LastPrice, MarkPrice, or IndexPrice\"\n        ),\n    }\n}\n\npub(crate) fn parse_tp_sl_order_type(s: &str) -> anyhow::Result<BybitOrderType> {\n    match s {\n        \"Market\" => Ok(BybitOrderType::Market),\n        \"Limit\" => Ok(BybitOrderType::Limit),\n        _ => anyhow::bail!(\"invalid Bybit TP/SL order type: '{s}', expected Market or Limit\"),\n    }\n}\n\n// A plain `serde_json` deserialize would accept unknown strings: `BybitTpSlMode` carries a\n// `#[serde(other)] Unknown` variant, so garbage would silently map to `Unknown`.\npub(crate) fn parse_tpsl_mode(s: &str) -> anyhow::Result<BybitTpSlMode> {\n    match s {\n        \"Full\" => Ok(BybitTpSlMode::Full),","sourceCodeStart":1941,"sourceCodeEnd":1977,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/common/parse.rs#L1941-L1977","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nlet tt = parse_trigger_type(\"last_price\")?; // fails\n// after\nlet tt = parse_trigger_type(\"LastPrice\")?; // exact Bybit casing","handlingStrategy":"validation","validationCode":"const TRIGGER_TYPES: [&str; 3] = [\"LastPrice\", \"MarkPrice\", \"IndexPrice\"];\nfn is_valid_trigger(s: &str) -> bool { TRIGGER_TYPES.contains(&s) }","typeGuard":"fn valid_trigger(s: &str) -> Option<BybitTriggerType> {\n    match s {\n        \"LastPrice\" => Some(BybitTriggerType::LastPrice),\n        \"MarkPrice\" => Some(BybitTriggerType::MarkPrice),\n        \"IndexPrice\" => Some(BybitTriggerType::IndexPrice),\n        _ => None,\n    }\n}","tryCatchPattern":"match parse_trigger_type(raw) {\n    Ok(tt) => proceed(tt),\n    Err(e) => { log::warn!(\"unsupported trigger type, skipping TPSL params: {e}\"); fallback(); }\n}","preventionTips":["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"],"tags":["bybit","parsing","enum-validation","tpsl"],"backgroundTag":"invalid-enum-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}