nautechsystems/nautilus_trader · error · anyhow::Error
Architect AX adapter cannot encode quote_quantity; submit a
Error message
Architect AX adapter cannot encode quote_quantity; submit a base quantity instead
What it means
validate_order_instructions rejects orders with quote_quantity=true: the AX order encoding accepts only a base-size (integer contract count, see quantity_to_contracts), so an order denominated in quote currency (e.g. 'buy $5,000 of BTC-PERP') cannot be encoded. The message tells you the unit mismatch directly - the adapter needs a base quantity instead. Checked at both submit validation and OrderInitialized validation.
Source
Thrown at crates/adapters/architect_ax/src/execution.rs:1923
fn validate_order_init_instructions(order_init: &OrderInitialized) -> anyhow::Result<()> {
validate_order_instructions(
order_init.reduce_only,
order_init.quote_quantity,
order_init.display_qty.is_some(),
)
}
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 {View on GitHub (pinned to a4b06ed870)
Solutions
- Compute base size = notional / reference_price and submit that base quantity instead
- Round to a whole number of contracts (AX quantities are integers; fractional contracts also fail later in quantity_to_contracts)
- Keep the reference-price logic in the strategy so the order you submit is already base-denominated
Example fix
// before
let order = factory.market(id, side, Quantity::from(5_000))
.quote_quantity(true); // $5000 notional -> error
// after
let base = (5_000.0 / mid_price).floor(); // whole contracts
let order = factory.market(id, side, Quantity::from(base)); Defensive patterns
Strategy: validation
Validate before calling
// Convert notional to base contracts before building the order let contracts = (notional / ref_price).floor(); ensure!(contracts >= 1.0, "notional too small for one contract"); let qty = Quantity::from(contracts as u64); // integer contracts only assert!(!order.is_quote_quantity());
Prevention
- Do notional-to-base conversion in the sizing layer so orders are always base-denominated
- Remember AX takes integer contract counts - fractional sizes fail even without quote_quantity
- Unit-test sizing helpers against the minimum contract size of each AX instrument
When it happens
Trigger: factory.market(...).quote_quantity(true) (or an OrderInitialized with quote_quantity set) submitted to the AX execution client; strategies that size entries in USD notional, common when porting from spot adapters.
Common situations: Notional-based position sizing code shared across venues; default templates from adapters where quote-quantity market buys are idiomatic.
Related errors
- Unsupported order type: {:?}, the Architect AX adapter accep
- Unsupported time in force: {:?}, AX supports GTC, IOC, and D
- AX does not support reduce-only orders
- Architect AX adapter cannot encode display_qty iceberg instr
- AX requires whole contract quantities, was {}
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/4568ab3abd25bd73.
Report an issue: GitHub.