nautechsystems/nautilus_trader · error · anyhow::Error

AX maintenance_margin_pct must be positive, was

Error message

AX maintenance_margin_pct must be positive, was {maintenance_margin_pct}

What it means

Validation in AX instrument parsing's parse_margin_rates: the parsed maintenance margin percentage is zero or negative, which cannot represent a valid margin requirement, so the instrument definition is rejected.

Solutions

  1. Inspect the venue's maintenance margin field for the instrument.
  2. Correct the upstream value to a positive percentage.
  3. Fix fixtures to carry realistic positive maintenance margins.
  4. Handle/filter instruments with missing margin data before parsing if they are not tradable.

Example fix

// before (payload)
"margin_maint_pct": "0"
// after
"margin_maint_pct": "0.05"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_maintenance_margin(v: Decimal) -> bool { v > Decimal::ZERO }

Prevention

When it happens

Trigger: parse_instrument (via request_instruments/request_instrument) on a definition where maintenance_margin_pct <= 0.

Common situations: Missing or zero-defaulted margin metadata from the venue, fixtures with placeholder zeros, negative values from a malformed feed.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

        .taker_fee(taker_fee)
        .info(info)
        .ts_event(ts_event)
        .ts_init(ts_init)
        .build()
        .unwrap();

    Ok(InstrumentAny::PerpetualContract(instrument))
}

fn parse_margin_rates(
    initial_margin_pct: Decimal,
    maintenance_margin_pct: Decimal,
) -> anyhow::Result<(Decimal, Decimal)> {
    anyhow::ensure!(
        initial_margin_pct > Decimal::ZERO,
        "AX initial_margin_pct must be positive, was {initial_margin_pct}"
    );
    anyhow::ensure!(
        maintenance_margin_pct > Decimal::ZERO,
        "AX maintenance_margin_pct must be positive, was {maintenance_margin_pct}"
    );
    anyhow::ensure!(
        maintenance_margin_pct <= initial_margin_pct,
        "AX maintenance_margin_pct {maintenance_margin_pct} exceeds initial_margin_pct {initial_margin_pct}"
    );

    Ok((
        margin_percent_to_rate(initial_margin_pct, "initial_margin_pct")?,
        margin_percent_to_rate(maintenance_margin_pct, "maintenance_margin_pct")?,
    ))
}

fn margin_percent_to_rate(value: Decimal, field: &str) -> anyhow::Result<Decimal> {
    let normalized = value.normalize();
    let scale = normalized.scale();
    anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)