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
- Use one of the exact eight modes: OPPONENT, OPPONENT_5, OPPONENT_10, OPPONENT_20, QUEUE, QUEUE_5, QUEUE_10, QUEUE_20 (any case)
- Check the offset suffix - only 5, 10 and 20 ticks exist, and the separator is an underscore
- 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
- Validate price_match at config load with the fixed allow-list, not at order time
- Copy the mode strings verbatim from Binance docs (underscore separators, offsets 5/10/20 only)
- Add a config lint step to CI for futures venue configs
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
- price_match cannot be combined with post-only orders
- price_match is not supported for order type {order_type:?}
- {standard_key_var} not found in config or environment
- {standard_secret_var} not found in config or environment
- filter {key:?} contains a non-string value
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/a84cf2fc760cb1eb.
Report an issue: GitHub.