nautechsystems/nautilus_trader · error · anyhow::Error

AX open-orders total_count must be non-negative, was {}

Error message

AX open-orders total_count must be non-negative, was {}

What it means

A defensive invariant check on a paginated open-orders response: the venue-reported total_count must be non-negative. anyhow::ensure! aborts the open-orders aggregation loop if AX returns a negative value, which would otherwise corrupt pagination termination logic. This indicates a malformed or semantically invalid API response rather than a request failure.

Source

Thrown at crates/adapters/architect_ax/src/http/client.rs:1997

        let mut offset = 0_i64;
        let mut expected_total = None;

        loop {
            let request_offset = i32::try_from(offset)
                .context("AX open-orders offset exceeds the documented int32 range")?;
            let params = GetOpenOrdersParams {
                account_id: None,
                limit: Some(PAGE_SIZE),
                offset: Some(request_offset),
                sort_ts: Some("desc".to_string()),
            };
            let response = self
                .inner
                .get_open_orders_page(&params)
                .await
                .map_err(|e| anyhow::anyhow!(e))?;

            anyhow::ensure!(
                response.total_count >= 0,
                "AX open-orders total_count must be non-negative, was {}",
                response.total_count
            );
            anyhow::ensure!(
                response.limit >= 0 && response.limit <= PAGE_SIZE,
                "AX open-orders applied limit must be between 0 and {PAGE_SIZE}, was {}",
                response.limit
            );
            anyhow::ensure!(
                i64::from(response.offset) == offset,
                "AX open-orders response offset mismatch: requested {offset}, was {}",
                response.offset
            );

            let total_count = *expected_total.get_or_insert(response.total_count);
            anyhow::ensure!(
                response.total_count == total_count,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check whether the AX API version changed and update the client's response models.
  2. Dump the raw response body to see what was actually returned.
  3. Confirm the request hit the correct open-orders endpoint (not an error page deserialized as a page).
  4. Report the malformed response to the AX venue/adapter maintainers if the API is unchanged.
Defensive patterns

Strategy: try-catch

Validate before calling

// after receiving a page, check invariants yourself
if response.total_count < 0 {
    return Err(anyhow!("malformed AX page: negative total_count {}", response.total_count));
}

Try / catch

match client.request_open_orders_paged().await {
    Ok(orders) => orders,
    Err(e) if e.to_string().contains("total_count") => {
        tracing::error!("AX returned malformed open-orders page: {e:#}");
        Vec::new() // or surface a schema-drift alert
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: Calling the paginated open-orders fetch when AX returns a page whose total_count field is negative — only possible if the response schema/serialization changed or a proxy/gateway returned unexpected body content.

Common situations: AX API version change altering the response schema; a misbehaving gateway or mock server returning placeholder values; deserializing an unrelated error body into the page struct due to a wrong endpoint or content-type.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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