nautechsystems/nautilus_trader · error · anyhow::Error

AX final-settlement fill must also be classified as a block…

Error message

AX final-settlement fill must also be classified as a block trade

What it means

In the AX adapter, a fill flagged as final settlement must also be flagged as a block trade. The two classifications drive venue_order_id synthesis for special fills, and a final-settlement fill without block classification is treated as inconsistent venue data, so parsing is rejected.

Solutions

  1. Check the raw fill payload flags (is_block_trade, is_final_settlement) from the AX API.
  2. If the venue data is inconsistent, obtain corrected fill records or re-fetch the affected fills.
  3. Filter the inconsistent fill and reconcile it manually with the venue.
  4. If a newer AX API decoupled these flags, update the adapter's parsing rules.

Example fix

// before (payload)
{ "trade_id": "T1", "is_block_trade": false, "is_final_settlement": true }
// after
{ "trade_id": "T1", "is_block_trade": true, "is_final_settlement": true }
Defensive patterns

Strategy: validation

Validate before calling

fn fill_flags_consistent(f: &AxFill) -> bool {
    !(f.is_final_settlement == Some(true) && f.is_block_trade == Some(false))
}

Prevention

When it happens

Trigger: parse_fill_report (via request_fill_reports) encountering a fill where is_final_settlement == Some(true) but is_block_trade == Some(false).

Common situations: AX venue sends inconsistent flags on expiry-day settlement fills; a venue API version change altering flag semantics; adapter consuming fills from a venue misconfiguring final settlement events.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — 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/7db90ff6ec65b7aa. Report an issue: GitHub.

Appendix: source

Thrown at crates/adapters/architect_ax/src/http/parse.rs:652

/// # Errors
///
/// Returns an error if:
/// - Price or quantity fields cannot be parsed.
/// - Fee parsing fails.
/// - Fill classification is inconsistent.
/// - A fill is neither explicitly special nor linked to a valid order ID.
pub fn parse_fill_report(
    fill: &AxFill,
    account_id: AccountId,
    instrument: &InstrumentAny,
    ts_init: UnixNanos,
) -> anyhow::Result<FillReport> {
    let instrument_id = instrument.id();

    let trade_id = TradeId::new_checked(&fill.trade_id).context("Invalid trade_id in Ax fill")?;
    let is_block_trade = fill.is_block_trade;
    let is_final_settlement = fill.is_final_settlement;
    anyhow::ensure!(
        !(is_final_settlement == Some(true) && is_block_trade == Some(false)),
        "AX final-settlement fill must also be classified as a block trade"
    );

    let is_special_fill = is_block_trade == Some(true) || is_final_settlement == Some(true);
    let venue_order_id = if is_special_fill {
        VenueOrderId::new_checked(format!("AX-FILL-{}", fill.trade_id))
            .context("Invalid synthetic venue order ID for AX fill")?
    } else {
        let order_id = fill
            .order_id
            .as_deref()
            .context("AX fill is missing order_id and explicit special-fill classification")?;
        anyhow::ensure!(
            !order_id.is_empty(),
            "AX regular fill has an empty order_id"
        );
        VenueOrderId::new_checked(order_id).context("Invalid order_id in AX fill")?

View on GitHub (pinned to 18893faf8b)