nautechsystems/nautilus_trader · error

price_match cannot be combined with post-only orders

Error message

price_match cannot be combined with post-only orders

What it means

Binance's `priceMatch` feature (activation by trailing price distance) is incompatible with post-only (GTX) orders, because a price-matched order can cross the book. If the `price_match` param is present and the Nautilus order is post-only, `validate_order` rejects the submission.

Solutions

  1. Set `post_only=false` on the order when using `price_match`.
  2. Remove the `price_match` param to keep the post-only limit order.
  3. Use `time_in_force` and regular limit pricing instead of price_match for maker entries.

Example fix

// before
let order = factory.limit(..., post_only=true);
params.insert("price_match", "OPPONENT");
// after
let order = factory.limit(..., post_only=false);
params.insert("price_match", "OPPONENT");
Defensive patterns

Strategy: validation

Validate before calling

fn check_price_match_post_only(order: &OrderAny, params: &Option<NautilusParams>) -> Result<(), String> {
    let pm = params.as_ref().and_then(|p| p.get_str("price_match"));
    if pm.is_some() && order.is_post_only() {
        return Err("price_match cannot be combined with post-only".into());
    }
    Ok(())
}

Type guard

fn price_match_ok(order: &OrderAny, params: &Option<NautilusParams>) -> bool {
    params.as_ref().and_then(|p| p.get_str("price_match")).is_none() || !order.is_post_only()
}

Try / catch

match client.submit_order(cmd).await {
    Err(e) if e.to_string().contains("price_match cannot be combined") => {
        // disable post_only or remove price_match, then resubmit
    }
    other => other?,
}

Prevention

When it happens

Trigger: Submitting a limit order to Binance futures with `params.price_match = "..."` (e.g. "OPPONENT" or a numeric distance) while the order was created with `post_only=true` (e.g. `Limit` order with `TimeInForce::Gtx` / post_only factory flag).

Common situations: Combining maker-only strategy config with price-match trailing activation; a strategy framework that globally sets post_only on all limit orders; copying params blocks between orders.

Related errors


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

Appendix: source

Thrown at crates/adapters/binance/src/futures/execution.rs:3678

            "`close_position` requires `reduce_only=true` on the Nautilus order"
        );
        anyhow::ensure!(
            matches!(
                order_type,
                OrderType::StopMarket | OrderType::MarketIfTouched
            ),
            "`close_position` is not supported for order type {order_type:?} on Binance"
        );
    }

    if let Some(price_match) = cmd
        .params
        .as_ref()
        .and_then(|params| params.get_str("price_match"))
    {
        BinancePriceMatch::from_param(price_match)?;
        let order_type = order.order_type();
        anyhow::ensure!(
            !order.is_post_only(),
            "price_match cannot be combined with post-only orders"
        );
        anyhow::ensure!(
            order_type == OrderType::Limit,
            "price_match is not supported for order type {order_type:?}"
        );
    }

    let lifetime = determine_futures_order_lifetime(
        client.product_type,
        order.order_type(),
        order.time_in_force(),
        order.expire_time(),
        order.is_post_only(),
        client.config.use_gtd,
        client.clock.get_time_ns(),
    )?;

View on GitHub (pinned to 18893faf8b)