nautechsystems/nautilus_trader · error · anyhow::Error

position_side SHORT conflicts with positive position_amt

Error message

position_side SHORT conflicts with positive position_amt

What it means

Mirror case of error 1840: when use_position_ids=true and Binance reports positionSide=SHORT, the sign of position_amt must be negative (short positions on Binance carry a negative amount). A positive amount alongside a SHORT side marker is contradictory, so create_position_report rejects the position risk record instead of emitting an inconsistent report.

Source

Thrown at crates/adapters/binance/src/futures/execution.rs:1029

        let entry_price: Decimal = position
            .entry_price
            .parse()
            .context("invalid entry_price")?;

        let position_side = if position_amount > Decimal::ZERO {
            PositionSide::Long
        } else {
            PositionSide::Short
        };

        if self.config.use_position_ids {
            match position.position_side {
                Some(BinancePositionSide::Long) => anyhow::ensure!(
                    position_side == PositionSide::Long,
                    "position_side LONG conflicts with negative position_amt"
                ),
                Some(BinancePositionSide::Short) => anyhow::ensure!(
                    position_side == PositionSide::Short,
                    "position_side SHORT conflicts with positive position_amt"
                ),
                _ => {}
            }
        }

        let venue_position_id = make_venue_position_id(
            self.config.use_position_ids,
            instrument_id,
            position.position_side,
        )?;

        if let Some(venue_position_id) = venue_position_id {
            self.ensure_cached_position_id_compatible(
                instrument_id,
                position_side,
                venue_position_id,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the account is in hedge mode consistently with adapter config (use_position_ids=true assumes hedge-mode style positionSide fields).
  2. Set use_position_ids=false in the exec client config to bypass side/ID consistency checks.
  3. Force a fresh reconciliation of position risk data to replace the stale snapshot.
  4. Close and flatten the affected position via the venue, then let the adapter rebuild state from an empty book.

Example fix

// keep hedge mode and venue IDs aligned
// before
BinanceFuturesExecClientConfig { use_position_ids: true } // account in one-way mode
// after
// switch Binance account to Hedge Mode, or:
BinanceFuturesExecClientConfig { use_position_ids: false }
Defensive patterns

Strategy: validation

Validate before calling

if cfg.use_position_ids {
    let amt: Decimal = position.position_amt.parse()?;
    if position.position_side == Some(BinancePositionSide::Short) && amt > Decimal::ZERO {
        log::warn!("inconsistent SHORT side with positive amt for {}", position.symbol);
    }
}

Prevention

When it happens

Trigger: create_position_report called from generate_position_status_reports with position.position_side == Some(BinancePositionSide::Short) while position_amt parses to a positive value; usually from stale or partially updated position risk data, or from one-way-mode records mislabeled as SHORT.

Common situations: Account switched out of hedge mode leaving stale side metadata; manual trades in the Binance web UI while the adapter reconciles; dual-side position records where the closing leg has not yet been applied server-side.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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