{"record":{"id":"191375d81e8a0b74","repo":"nautechsystems/nautilus_trader","slug":"ax-maintenance-margin-pct-must-be-positive-was-m","errorCode":null,"errorMessage":"AX maintenance_margin_pct must be positive, was {maintenance_margin_pct}","messagePattern":"AX maintenance_margin_pct must be positive, was (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/http/parse.rs","lineNumber":388,"sourceCode":"        Some(taker_fee),\n        None,\n        Some(info),\n        ts_event,\n        ts_init,\n    );\n\n    Ok(InstrumentAny::PerpetualContract(instrument))\n}\n\nfn parse_margin_rates(\n    initial_margin_pct: Decimal,\n    maintenance_margin_pct: Decimal,\n) -> anyhow::Result<(Decimal, Decimal)> {\n    anyhow::ensure!(\n        initial_margin_pct > Decimal::ZERO,\n        \"AX initial_margin_pct must be positive, was {initial_margin_pct}\"\n    );\n    anyhow::ensure!(\n        maintenance_margin_pct > Decimal::ZERO,\n        \"AX maintenance_margin_pct must be positive, was {maintenance_margin_pct}\"\n    );\n    anyhow::ensure!(\n        maintenance_margin_pct <= initial_margin_pct,\n        \"AX maintenance_margin_pct {maintenance_margin_pct} exceeds initial_margin_pct {initial_margin_pct}\"\n    );\n\n    Ok((\n        margin_percent_to_rate(initial_margin_pct, \"initial_margin_pct\")?,\n        margin_percent_to_rate(maintenance_margin_pct, \"maintenance_margin_pct\")?,\n    ))\n}\n\nfn margin_percent_to_rate(value: Decimal, field: &str) -> anyhow::Result<Decimal> {\n    let normalized = value.normalize();\n    let scale = normalized.scale();\n    anyhow::ensure!(","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/architect_ax/src/http/parse.rs#L370-L406","documentation":"parse_margin_rates requires maintenance_margin_pct to be strictly greater than zero before percent-to-rate conversion. A zero or negative maintenance percent — usually an unset field — aborts parsing of the instrument, even when the initial margin is valid.","triggerScenarios":"An instrument definition arrives with maintenance_margin_pct 0 (unconfigured listing) or negative, while initial_margin_pct may be fine; the load of that symbol fails inside parse_margin_rates.","commonSituations":"Margin config partially filled — initial set but maintenance left at default 0; API field renames causing zero-default deserialization; venues that do not distinguish maintenance margin (values omitted).","solutions":["Set a positive maintenance_margin_pct for the symbol in AX venue config","Confirm the API field mapping for your version so the value is not silently defaulted to 0","If the venue truly has no separate maintenance tier, set it equal to (not exceeding) the initial margin percent","Reload instruments after the config fix"],"exampleFix":"// before (AX contract metadata)\n\"maintenance_margin_pct\": \"0\"\n// after\n\"maintenance_margin_pct\": \"0.5\"","handlingStrategy":"try-catch","validationCode":"// Vet margin fields before definitions reach the parser\nfn maintenance_margin_ok(v: Decimal) -> bool { v > Decimal::ZERO }\n\nif !maintenance_margin_ok(definition.maintenance_margin_pct) {\n    anyhow::bail!(\"symbol {} has non-positive maintenance_margin_pct {}}\", definition.symbol, definition.maintenance_margin_pct);\n}","typeGuard":null,"tryCatchPattern":"match parse_instrument(&definition, ts_event, ts_init) {\n    Ok(instrument) => Ok(instrument),\n    Err(e) if e.to_string().contains(\"maintenance_margin_pct must be positive\") => {\n        log::error!(\"symbol {} margin config incomplete (maintenance_margin_pct <= 0)\", definition.symbol);\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Require both margin percents (not just initial) in venue config validation","When a venue has no separate maintenance tier, configure it equal to the initial margin","Re-run instrument loads after every margin config change and assert parse success"],"tags":["architect-ax","instrument","margin","validation","metadata"],"backgroundTag":"invalid-margin-parameters","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}