nautechsystems/nautilus_trader · error · anyhow::Error

Invalid price_match value: {s:?}

Error message

Invalid price_match value: {s:?}

What it means

BinancePriceMatch::from_param parses a price match mode from a config string; the first branch fires when the (uppercased) value does not deserialize into any BinancePriceMatch variant at all - it is not a recognized Binance price match mode string.

Source

Thrown at crates/adapters/binance/src/common/enums.rs:505

    #[serde(rename = "QUEUE_20")]
    Queue20,
    /// Unknown or undocumented value.
    #[serde(other)]
    Unknown,
}

impl BinancePriceMatch {
    /// Parses a price match mode from a string param value.
    ///
    /// Accepts uppercase Binance API values like `"OPPONENT"`, `"OPPONENT_5"`, `"QUEUE_10"`.
    ///
    /// # Errors
    ///
    /// Returns an error if the value is not a recognized price match mode.
    pub fn from_param(s: &str) -> anyhow::Result<Self> {
        let value = s.to_uppercase();
        serde_json::from_value(serde_json::Value::String(value))
            .map_err(|_| anyhow::anyhow!("Invalid price_match value: {s:?}"))
            .and_then(|pm: Self| {
                if pm == Self::None || pm == Self::Unknown {
                    anyhow::bail!("Invalid price_match value: {s:?}")
                }
                Ok(pm)
            })
    }
}

/// Self-trade prevention mode.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum BinanceSelfTradePreventionMode {
    /// No self-trade prevention.
    None,
    /// Expire maker orders on self-trade.
    ExpireMaker,
    /// Expire taker orders on self-trade.

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Use one of the exact eight modes: OPPONENT, OPPONENT_5, OPPONENT_10, OPPONENT_20, QUEUE, QUEUE_5, QUEUE_10, QUEUE_20 (any case)
  2. Check the offset suffix - only 5, 10 and 20 ticks exist, and the separator is an underscore
  3. Copy the value verbatim from the Binance price match documentation for your endpoint

Example fix

# before
price_match = "OPPONENT_7"

# after
price_match = "OPPONENT_10"
Defensive patterns

Strategy: validation

Validate before calling

const VALID_PRICE_MATCH: &[&str] = &["OPPONENT","OPPONENT_5","OPPONENT_10","OPPONENT_20","QUEUE","QUEUE_5","QUEUE_10","QUEUE_20"];
fn is_valid_price_match(s: &str) -> bool {
    VALID_PRICE_MATCH.contains(&s.to_uppercase().as_str())
}

Type guard

fn is_valid_price_match_param(s: &str) -> bool {
    let v = s.to_uppercase();
    matches!(v.as_str(), "OPPONENT"|"OPPONENT_5"|"OPPONENT_10"|"OPPONENT_20"|"QUEUE"|"QUEUE_5"|"QUEUE_10"|"QUEUE_20")
}

Try / catch

if let Err(e) = BinancePriceMatch::from_param(&cfg.price_match) {
    return Err(config_error(format!("invalid price_match '{}': {e}", cfg.price_match)));
}

Prevention

When it happens

Trigger: Passing a price_match parameter whose value is not one of OPPONENT, OPPONENT_5, OPPONENT_10, OPPONENT_20, QUEUE, QUEUE_5, QUEUE_10, QUEUE_20 (case-insensitive) - e.g. "OPPONENT_7", "OPPONENT-5", or "oponnent".

Common situations: Hand-typed futures config with a typo in the mode or tick-offset suffix; values copied from a different Binance API section; stale config from when the feature set differed.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/a84cf2fc760cb1eb. Report an issue: GitHub.