nautechsystems/nautilus_trader · error
initial_margin_fraction must be in 1..=10_000, was {initial_
Error message
initial_margin_fraction must be in 1..=10_000, was {initial_margin_fraction} What it means
Lighter's initial_margin_fraction is expressed in basis-point-like units and must be between 1 and 10,000 inclusive (i.e. leverage between 10,000x and 1x). update_leverage validates the requested value up front and rejects anything outside that range.
Source
Thrown at crates/adapters/lighter/src/execution.rs:2083
/// Returns an error if credentials are missing, the instrument is not
/// registered, `initial_margin_fraction` is outside `1..=10_000`, or
/// the dispatch pre-flight (nonce allocation, signing) fails. Transport
/// errors after dispatch are logged but not returned synchronously.
pub fn update_leverage(
&self,
instrument_id: InstrumentId,
initial_margin_fraction: u16,
margin_mode: LighterPositionMarginMode,
) -> anyhow::Result<()> {
let credential = self.credential.as_ref().ok_or_else(|| {
anyhow::anyhow!("Lighter execution client cannot update leverage without credentials")
})?;
let market_index = self.registry.market_index(&instrument_id).ok_or_else(|| {
anyhow::anyhow!("no Lighter market_index registered for instrument {instrument_id}")
})?;
anyhow::ensure!(
(1..=10_000).contains(&initial_margin_fraction),
"initial_margin_fraction must be in 1..=10_000, was {initial_margin_fraction}",
);
let ReservedTxContext {
context,
mut send_reservation,
} = self.build_tx_context(credential)?;
let connection_epoch = send_reservation.connection_epoch;
let captured_nonce = context.nonce;
let captured_api_key_index = context.api_key_index;
let mut rollback_guard =
TxDispatchGuard::new(self.dispatch.clone(), credential, None, captured_nonce);
let tx = UpdateLeverageTxInfo {
context,View on GitHub (pinned to 18893faf8b)
Solutions
- Convert leverage to margin fraction: initial_margin_fraction = 10_000 / leverage (e.g. 20x -> 500).
- Clamp/validate the value into 1..=10_000 before calling update_leverage.
- If you meant to raise leverage, decrease the fraction, not increase it.
Example fix
// before client.update_leverage(iid, 25 /* intended 25x */, mode).await?; // out of range semantics // after let imf = (10_000 / leverage).clamp(1, 10_000); client.update_leverage(iid, imf, mode).await?;
Defensive patterns
Strategy: validation
Validate before calling
let imf = 10_000u32.checked_div(leverage).ok_or("leverage must be >= 1")?;
assert!((1..=10_000).contains(&imf), "imf {imf} out of 1..=10_000"); Try / catch
if let Err(e) = client.update_leverage(iid, imf, mode).await {
if e.to_string().contains("initial_margin_fraction must be") {
let clamped = imf.clamp(1, 10_000);
client.update_leverage(iid, clamped, mode).await?;
}
} Prevention
- Convert leverage to margin fraction (10_000 / leverage) once, in one helper.
- Add a clamping helper so every caller passes an in-range value.
- Document the units in your strategy config schema to avoid percent/multiplier mixups.
When it happens
Trigger: update_leverage called with initial_margin_fraction of 0, negative (if passed as a wider integer), or > 10,000 — e.g. passing a percentage like 50 meaning 50% but which is actually valid only via inverse units, or confusing this field with leverage multiplier.
Common situations: Passing leverage (e.g. 20) where the API wants margin fraction, or margin fraction 0.05 where an integer 1..=10_000 is expected; copy-pasted defaults from another exchange adapter; UI sending percent values.
Related errors
- leverage requires spot_account_type=Margin (current: Cash)
- Invalid leverage {leverage} for {}
- Leverage tiers not loaded for {raw_symbol}; cannot validate
- Lighter execution client cannot update leverage without cred
- IncompleteOrderReports { reports, detail: detail.into() }
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c47e03df20fa7d27.
Report an issue: GitHub.