nautechsystems/nautilus_trader · error
invalid Bybit smp_type: '{s}', expected None, CancelMaker, C
Error message
invalid Bybit smp_type: '{s}', expected None, CancelMaker, CancelTaker or CancelBoth What it means
parse_smp_type parses a user-supplied self-match-prevention (smp_type) string into the BybitOrderSmpType enum. Matching is case-insensitive over the fixed set none/cancelmaker/canceltaker/cancelboth; any other string raises this anyhow error. It is reached via order submission (py_submit_order, py_new), TP/SL params, or config deserialization.
Source
Thrown at crates/adapters/bybit/src/common/parse.rs:1740
} else if let Some(n) = value.as_i64() {
Some(n.to_string())
} else {
value.as_u64().map(|n| n.to_string())
}
}
/// Parses a Bybit self-match prevention type from an order parameter or configuration value.
///
/// # Errors
///
/// Returns an error for any value outside the four types Bybit accepts on an order.
pub fn parse_smp_type(s: &str) -> anyhow::Result<BybitOrderSmpType> {
match s.to_ascii_lowercase().as_str() {
"none" => Ok(BybitOrderSmpType::None),
"cancelmaker" => Ok(BybitOrderSmpType::CancelMaker),
"canceltaker" => Ok(BybitOrderSmpType::CancelTaker),
"cancelboth" => Ok(BybitOrderSmpType::CancelBoth),
_ => anyhow::bail!(
"invalid Bybit smp_type: '{s}', expected None, CancelMaker, CancelTaker or CancelBoth"
),
}
}
/// Deserializes an optional self-match prevention type for a client configuration.
///
/// Routes the configured text through [`parse_smp_type`] so a serialized config reports an unknown
/// value instead of carrying it silently.
///
/// # 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);View on GitHub (pinned to 18893faf8b)
Solutions
- Use exactly one of: none, cancelmaker, canceltaker, cancelboth (case does not matter)
- Check the config/order params for stray prefixes, underscores or hyphens and remove them
- If SMP is not needed, set smp_type to none or omit it
Example fix
// before
params.insert("smp_type", "CANCEL_MAKER");
// after
params.insert("smp_type", "CancelMaker"); Defensive patterns
Strategy: validation
Validate before calling
VALID_SMP_TYPES = {"none", "cancelmaker", "canceltaker", "cancelboth"}
assert smp_type.lower() in VALID_SMP_TYPES, f"invalid smp_type: {smp_type}" Type guard
fn is_valid_smp_type(s: &str) -> bool {
matches!(s.to_ascii_lowercase().as_str(), "none" | "cancelmaker" | "canceltaker" | "cancelboth")
} Try / catch
match parse_smp_type(s) {
Ok(t) => use(t),
Err(e) => { log::error!("{e}"); BybitOrderSmpType::None }
} Prevention
- Use only the four accepted values, without underscores or hyphens
- Centralize smp_type constants instead of inlining strings
- Values are case-insensitive, but keep canonical CamelCase in configs
When it happens
Trigger: Passing smp_type as an order/TP-SL param or in client config with a misspelled or unsupported value, e.g. 'CANCEL_MAKER', 'cancel-maker', 'smptype_cancelboth', or an empty string.
Common situations: Config mistakes copying values from another exchange adapter's naming convention (snake_case or prefixed), typos, or leaving a placeholder value in the config file.
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 bbo_side_type: '{s}', expected Queue or Counte
- invalid 'bbo_level': '{s}', expected 1, 2, 3, 4, or 5
- TP override fields require 'take_profit' to be set
- Batch cancel limit is {endpoint_limit} orders for {product_t
- WS modify order failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6cbe2da41cf04042.
Report an issue: GitHub.