nautechsystems/nautilus_trader · error · anyhow::Error

Architect AX adapter cannot encode display_qty iceberg instr

Error message

Architect AX adapter cannot encode display_qty iceberg instructions

What it means

validate_order_instructions bails when the order has display_qty set: display_qty is the iceberg (hidden quantity) instruction, and AX's order model as encoded by this adapter has no field for it. Any OrderInitialized or submitted order carrying a display quantity is denied locally rather than sent with the iceberg semantics silently dropped - otherwise the venue would execute the full size visibly, changing the order's meaning.

Source

Thrown at crates/adapters/architect_ax/src/execution.rs:1929

}

fn validate_order_instructions(
    reduce_only: bool,
    quote_quantity: bool,
    has_display_qty: bool,
) -> anyhow::Result<()> {
    if reduce_only {
        anyhow::bail!("AX does not support reduce-only orders");
    }

    if quote_quantity {
        anyhow::bail!(
            "Architect AX adapter cannot encode quote_quantity; submit a base quantity instead"
        );
    }

    if has_display_qty {
        anyhow::bail!("Architect AX adapter cannot encode display_qty iceberg instructions");
    }

    Ok(())
}

// The AX HTTP API documents only a bare 400 with no error schema, so no venue
// failure can be allowlisted as an unambiguous rejection; those arrive via the
// orders WS `Rejected` and `CancelRejected` events instead. AX therefore never
// classifies a send failure as `CommandFailure::VenueRejected`.
fn classify_ax_http_failure(error: &AxHttpError) -> CommandFailure {
    let message = error.to_string();
    match error {
        AxHttpError::MissingCredentials
        | AxHttpError::MissingSessionToken
        | AxHttpError::ValidationError(_)
        | AxHttpError::BuildError(_) => CommandFailure::NotSent(message),
        AxHttpError::ApiError { .. }
        | AxHttpError::JsonError(_)

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Remove display_qty and submit the full visible LIMIT order
  2. Emulate iceberg locally: slice into child LIMIT orders yourself and resubmit as each child fills
  3. Gate your order builder so display_qty is never attached for instruments routed to AX

Example fix

// before
let order = factory.limit(id, side, qty, px)
    .display_qty(display); // -> cannot encode display_qty
// after: manual slicing
for slice_qty in qty.split_into(max_show) {
    self.submit_order(&factory.limit(id, side, slice_qty, px));
}
Defensive patterns

Strategy: validation

Validate before calling

if order.display_qty().is_some() {
    anyhow::bail!(
        "refusing to submit iceberg to AX; slice into child LIMIT orders instead"
    );
}

Prevention

When it happens

Trigger: factory.limit(...).display_qty(hidden) submitted to AX; order templates built for venues with native iceberg support (e.g. Binance) reused against AX.

Common situations: Execution algos that slice large parents and submit icebergs; shared order-building helpers that always populate display_qty when provided.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/05e360fbd0cb58ca. Report an issue: GitHub.