nautechsystems/nautilus_trader · error · anyhow::Error

Failed to send order denied event: {e}

Error message

Failed to send order denied event: {e}

What it means

This error wraps a failure to deliver an OrderDenied event over the exec_sender channel while rejecting an order whose `post_only` flag is not supported by Interactive Brokers. It is a secondary error: the adapter tries to report the denial to the execution engine, and if the event channel itself is closed/saturated, the send failure becomes this anyhow error. The original denial reason (post_only unsupported) is then raised with anyhow::bail!.

Source

Thrown at crates/adapters/interactive_brokers/src/execution/core_orders.rs:46

        clock: &'static AtomicTime,
        account_id: AccountId,
        order_submit_lock: &Arc<tokio::sync::Mutex<()>>,
    ) -> anyhow::Result<()> {
        if cmd.order_init.post_only {
            let ts_event = clock.get_time_ns();
            let event = OrderDenied::new(
                cmd.order_init.trader_id,
                cmd.strategy_id,
                cmd.instrument_id,
                cmd.order_init.client_order_id,
                Ustr::from("`post_only` not supported by Interactive Brokers"),
                UUID4::new(),
                ts_event,
                ts_event,
            );
            exec_sender
                .send(ExecutionEvent::Order(OrderEventAny::Denied(event)))
                .map_err(|e| anyhow::anyhow!("Failed to send order denied event: {e}"))?;
            anyhow::bail!("`post_only` not supported by Interactive Brokers");
        }

        let is_inverse = instrument_provider
            .find(&cmd.instrument_id)
            .map(|instrument| instrument.is_inverse())
            .unwrap_or(false);

        if cmd.order_init.quote_quantity && !is_inverse {
            let ts_event = clock.get_time_ns();
            let event = OrderDenied::new(
                cmd.order_init.trader_id,
                cmd.strategy_id,
                cmd.instrument_id,
                cmd.order_init.client_order_id,
                Ustr::from("UNSUPPORTED_QUOTE_QUANTITY"),
                UUID4::new(),
                ts_event,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set post_only = false on the order (or omit it); emulate maker-only behavior with an IB limit order and LEE/MKT TIF instead.
  2. Use an order type supported by IB (limit orders only for post-only-like behavior).
  3. Check that the adapter's execution event channel is alive; reconnect the execution client if the send itself failed.
  4. Inspect the chained error message from the send (the {e} payload) to distinguish channel failure from the intended denial.

Example fix

// before
let cmd = SubmitOrder::new(..., post_only: true, ...);
// after
let cmd = SubmitOrder::new(..., post_only: false, ...); // IB does not support post_only
Defensive patterns

Strategy: validation

Validate before calling

if order_init.post_only {
    return Err(anyhow::anyhow!("IB adapter does not support post_only orders"));
}

Prevention

When it happens

Trigger: Submitting an order via handle_submit_order_async with order_init.post_only set to true while using the Interactive Brokers adapter; the send itself fails only when the execution event channel is closed or disconnected.

Common situations: Users porting Binance-style post_only (maker-only) orders to IB, which expresses this via TIF/time-in-force semantics rather than a post_only flag; also occurs when the adapter's exec sender was shut down (adapter disconnect) mid-submission.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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