nautechsystems/nautilus_trader · error

Invalid price_match value

Error message

Invalid price_match value: {s:?}

What it means

PriceMatch is Binance's price-match/counterparty-best-match feature (e.g. OPPONENT, MAKER side values). from_param parses a case-insensitive string parameter via serde into the enum, then rejects both the explicit None and Unknown variants, since those are not valid requested price_match settings. Any string that neither deserializes to a variant nor passes that filter raises this error.

Solutions

  1. Pass a valid Binance price_match value: OPPONENT, or the maker-side variants accepted by the enum (e.g. MAKER_SIDE), with any casing.
  2. Omit the price_match parameter entirely instead of passing "None".
  3. Validate the config value against the enum's serializable variants at startup.
  4. Check Binance's current API docs for the accepted price_match set if a valid-looking value still fails.

Example fix

// before
let pm = PriceMatch::from_param("none")?; // rejected: None variant not allowed
// after
let pm = if price_match_param.is_empty() {
    None // omit the feature
} else {
    Some(PriceMatch::from_param(&price_match_param)?) // e.g. "OPPONENT"
};
Defensive patterns

Strategy: validation

Validate before calling

const VALID_PRICE_MATCH: [&str; 3] = ["OPPONENT", "MAKER_SIDE", "TAKER_SIDE"];
let norm = param.to_uppercase();
assert!(VALID_PRICE_MATCH.contains(&norm.as_str()), "invalid price_match: {param}");

Type guard

fn is_valid_price_match_param(s: &str) -> bool {
    matches!(s.to_uppercase().as_str(), "OPPONENT" | "MAKER_SIDE" | "TAKER_SIDE")
}

Try / catch

match PriceMatch::from_param(param) {
    Ok(pm) => Some(pm),
    Err(e) if e.to_string().contains("Invalid price_match value") => {
        log::warn!("ignoring invalid price_match {param:?}");
        None
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling PriceMatch::from_param with a string that is not a recognized Binance price_match value (case-insensitive) — e.g. "none", "unknown", "best-match", or any typo like "oponents".

Common situations: Reading the price_match option from a config file or query parameter with an unexpected default ("none"); typos or wrong casing conventions in user config; copying values from another exchange's API that uses different naming.

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


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

Appendix: source

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

    #[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.
    ExpireTaker,
    /// Expire both sides on self-trade.
    ExpireBoth,

View on GitHub (pinned to 18893faf8b)