nautechsystems/nautilus_trader · error

Unsupported order type for Betfair

Error message

Unsupported order type for Betfair: {other:?}

What it means

The Betfair order translator maps supported Nautilus order types (Limit, LimitOnClose, MarketOnClose) to Betfair PlaceInstructions. Any other order variant (e.g. Market, Stop, TrailingStop) hits the catch-all `other` arm and bails with this error naming the variant.

Solutions

  1. Restrict strategies on Betfair to Limit, LimitOnClose, and MarketOnClose orders
  2. Pre-filter unsupported order types before submitting (match on OrderType and skip/convert)
  3. Emulate stop behavior in strategy logic if stops are needed on Betfair

Example fix

// before
let order = order_factory.stop_market(instrument_id, side, qty, trigger_price, ...);
// after
let order = order_factory.limit(instrument_id, side, qty, limit_price, TimeInForce::Gtc, ...);
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED: &[OrderType] = &[OrderType::Limit, OrderType::LimitOnClose, OrderType::MarketOnClose];
if !SUPPORTED.contains(&order.order_type()) {
    return Err(anyhow!("{} not supported on Betfair", order.order_type()));
}

Type guard

fn betfair_supported(o: &dyn Order) -> bool {
    matches!(o.order_type(), OrderType::Limit | OrderType::LimitOnClose | OrderType::MarketOnClose)
}

Try / catch

match submit_result {
    Err(e) if e.to_string().contains("Unsupported order type for Betfair") => {
        eprintln!("use Limit/LimitOnClose/MarketOnClose");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the order conversion (build PlaceInstruction path) with an unsupported OrderType such as Market (without AtTheClose, see separate check), StopMarket, StopLimit, or TrailingStopMarket.

Common situations: Strategies written for other venues submitting stop or plain market orders to Betfair; dynamic order routing sending every order type to the adapter; backtest code assumptions carried into live Betfair execution.

Related errors


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

Appendix: source

Thrown at crates/adapters/betfair/src/execution.rs:3436

            if order.time_in_force() != TimeInForce::AtTheClose {
                anyhow::bail!(
                    "Market orders on Betfair are only supported with AtTheClose \
                     time in force (BSP MarketOnClose)"
                );
            }

            Ok(PlaceInstruction {
                order_type: BetfairOrderType::MarketOnClose,
                selection_id,
                handicap,
                side,
                limit_order: None,
                limit_on_close_order: None,
                market_on_close_order: Some(MarketOnCloseOrder { liability: size }),
                customer_order_ref,
            })
        }
        other => anyhow::bail!("Unsupported order type for Betfair: {other:?}"),
    }
}

fn customer_order_ref_collision_reason(customer_order_ref: &str) -> String {
    OrderDeniedReason::ValidationFailed {
        detail: format!(
            "customerOrderRef {customer_order_ref} collides with another tracked order"
        ),
    }
    .to_string()
}

// Even states admit submissions; each halt advances to a distinct odd generation.
// The commit lock makes generation validation, publication, and reopening one boundary.
#[derive(Debug)]
struct ReconciliationGate {
    state: AtomicU64,
    commit_lock: Mutex<()>,

View on GitHub (pinned to 18893faf8b)