nautechsystems/nautilus_trader · error · anyhow::Error

Execution PostOnly not supported for {order_type:?}

Error message

Execution PostOnly not supported for {order_type:?}

What it means

PostOnly execution is only valid for plain limit orders on dYdX. `calculate_time_in_force` maps order type + execution to TimeInForce, and throws when a PostOnly execution is combined with StopMarket, TakeProfitMarket (and other non-limit order types).

Source

Thrown at crates/adapters/dydx/src/http/parse.rs:213

            DydxTimeInForce::Gtt => Ok(TimeInForce::Gtc),
            DydxTimeInForce::Fok => Ok(TimeInForce::Fok),
            DydxTimeInForce::Ioc => Ok(TimeInForce::Ioc),
        },

        DydxOrderType::StopLimit | DydxOrderType::TakeProfitLimit => match execution {
            Some(DydxOrderExecution::PostOnly) => Ok(TimeInForce::Gtc), // Post-only is GTC with post_only flag
            Some(DydxOrderExecution::Fok) => Ok(TimeInForce::Fok),
            Some(DydxOrderExecution::Ioc) => Ok(TimeInForce::Ioc),
            Some(DydxOrderExecution::Default) | None => Ok(TimeInForce::Gtc), // Default for conditional limit
        },

        DydxOrderType::StopMarket | DydxOrderType::TakeProfitMarket => match execution {
            Some(DydxOrderExecution::Fok) => Ok(TimeInForce::Fok),
            Some(DydxOrderExecution::Ioc | DydxOrderExecution::Default) | None => {
                Ok(TimeInForce::Ioc)
            }
            Some(DydxOrderExecution::PostOnly) => {
                anyhow::bail!("Execution PostOnly not supported for {order_type:?}")
            }
        },

        DydxOrderType::TrailingStop => Ok(TimeInForce::Gtc),
    }
}

/// Validate conditional order parameters.
///
/// Ensures that trigger prices are set correctly relative to limit prices
/// based on order type and side.
///
/// # Errors
///
/// Returns an error if:
/// - Conditional order is missing trigger price.
/// - Trigger price is on wrong side of limit price for the order type.
pub fn validate_conditional_order(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use `Fok` or `Ioc` (or omit execution) for stop-market and take-profit-market orders
  2. Reserve `PostOnly` for `Limit`/`StopLimit`/`TakeProfitLimit` order types only

Example fix

// before
let tif = calculate_time_in_force(DydxOrderType::StopMarket, Some(DydxOrderExecution::PostOnly))?;
// after
let tif = calculate_time_in_force(DydxOrderType::StopMarket, Some(DydxOrderExecution::Ioc))?;
Defensive patterns

Strategy: validation

Validate before calling

fn supports_post_only(t: DydxOrderType) -> bool {
    matches!(t, DydxOrderType::Limit | DydxOrderType::StopLimit | DydxOrderType::TakeProfitLimit)
}

Prevention

When it happens

Trigger: Submitting a stop-market or take-profit-market order with `DydxOrderExecution::PostOnly`, causing the time-in-force derivation to fail.

Common situations: Copying PostOnly options from limit order code into conditional/market order builders; user config enabling post-only globally for all order types.

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/6616e8f126bf7d90. Report an issue: GitHub.