nautechsystems/nautilus_trader · error · anyhow::Error

Failed to convert price to u64

Error message

Failed to convert price to u64

What it means

quantize_price rounds a dYdX price into subticks and must return it as u64 for the proto Order. The error is thrown when the quantized Decimal cannot fit into u64 (negative, fractional residue, or exceeding u64::MAX), meaning the price or market subticks_per_tick parameters are nonsensical.

Source

Thrown at crates/adapters/dydx/src/grpc/order.rs:135

            - self.quantum_conversion_exponent
            - QUOTE_QUANTUMS_ATOMIC_RESOLUTION);

        // When exponent is negative, we multiply by 10^|exponent|
        // When exponent is positive, we divide by 10^exponent (multiply by 10^-exponent)
        let factor = if exponent < 0 {
            Decimal::from(10_i64.pow(exponent.unsigned_abs()))
        } else {
            Decimal::new(1, exponent.unsigned_abs())
        };

        let raw_subticks = price * factor;
        let subticks_per_tick = Decimal::from(self.subticks_per_tick);
        let quantums = Self::quantize(&raw_subticks, &subticks_per_tick);
        let result = quantums.max(subticks_per_tick);

        result
            .to_u64()
            .ok_or_else(|| anyhow::anyhow!("Failed to convert price to u64"))
    }

    /// Convert decimal into quantums.
    ///
    /// # Errors
    ///
    /// Returns an error if conversion fails.
    pub fn quantize_quantity(&self, quantity: Decimal) -> Result<u64, anyhow::Error> {
        // When atomic_resolution is negative, we multiply by 10^|atomic_resolution|
        // When atomic_resolution is positive, we divide by 10^atomic_resolution
        let factor = if self.atomic_resolution < 0 {
            Decimal::from(10_i64.pow(self.atomic_resolution.unsigned_abs()))
        } else {
            Decimal::new(1, self.atomic_resolution.unsigned_abs())
        };

        let raw_quantums = quantity * factor;
        let step_base_quantums = Decimal::from(self.step_base_quantums);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Validate the raw price is positive and within a sane range before calling market_order_subticks
  2. Verify market_params.subticks_per_tick matches the dYdX market's actual configuration (fetch from markets endpoint)
  3. Check where the oracle price comes from — a wrong unit multiplier can inflate the price enormously
  4. If the price is legitimately huge, cap/clamp it or reject the order upstream instead of relying on this conversion

Example fix

// before
let subticks = builder.build()?.quantize_price(raw_price)?;
// after
anyhow::ensure!(raw_price > Decimal::ZERO, "price must be positive");
anyhow::ensure!(raw_price < Decimal::from(1_000_000_000u64), "price out of sane range");
let subticks = builder.build()?.quantize_price(raw_price)?;
Defensive patterns

Strategy: validation

Validate before calling

anyhow::ensure!(raw_price.is_sign_positive(), "price must be positive");
anyhow::ensure!(raw_price <= Decimal::from(u64::MAX), "price exceeds u64 range");

Type guard

fn is_representable_u64(d: &Decimal) -> bool {
    d.is_sign_positive() && d <= Decimal::from(u64::MAX)
}

Prevention

When it happens

Trigger: Calling market_order_subticks (directly or via build for market/stop-market orders) with an oracle price so large that quantization exceeds u64::MAX, a negative raw price, or a market with a subticks_per_tick value that makes quantums.max(subticks_per_tick) unrepresentable.

Common situations: Corrupt or absurd oracle price data; a misconfigured market where subticks_per_tick is huge or zero/negative; passing a price already denominated in the wrong units (e.g. raw not human price); a Decimal that lost its scale via a bad conversion upstream.

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/2d9713079bd6301a. Report an issue: GitHub.