nautechsystems/nautilus_trader · critical · anyhow::Error

Invalid fixed-point raw value {raw} for precision {precision

Error message

Invalid fixed-point raw value {raw} for precision {precision}: remainder {remainder} when divided by scale {scale}. Raw value should be a multiple of {scale}. This indicates data corruption or incorrect precision/scaling upstream

What it means

Nautilus fixed-point types store values as raw integers that must be exact multiples of 10^scale for the declared precision. When a validity check (`check_fixed_raw_u128/u64/i128/i64`) finds the raw value has a non-zero remainder after division by the scale factor, the value cannot be represented exactly and this error is thrown, explicitly flagging data corruption or an upstream precision/scaling mistake rather than silently truncating.

Source

Thrown at crates/model/src/types/fixed.rs:408

    #[cfg(not(feature = "defi"))]
    debug_assert!(
        precision <= FIXED_PRECISION,
        "precision {precision} exceeds FIXED_PRECISION {FIXED_PRECISION}: \
         raw value validation is not possible at this precision"
    );

    precision >= FIXED_PRECISION
}

/// Builds the error for invalid fixed-point raw values (cold path).
#[cold]
fn invalid_raw_error(
    raw: impl Display,
    precision: u8,
    remainder: impl Display,
    scale: impl Display,
) -> anyhow::Error {
    anyhow::anyhow!(
        "Invalid fixed-point raw value {raw} for precision {precision}: \
         remainder {remainder} when divided by scale {scale}. \
         Raw value should be a multiple of {scale}. \
         This indicates data corruption or incorrect precision/scaling upstream"
    )
}

/// Checks that a raw unsigned fixed-point value has no spurious bits beyond the precision scale.
///
/// For a given precision P where P < `FIXED_PRECISION`, valid raw values must be exact
/// multiples of `10^(FIXED_PRECISION` - P). Any non-zero remainder indicates data corruption
/// or incorrect scaling upstream.
///
/// # Precision Limits
///
/// This check only validates when `precision < FIXED_PRECISION`:
/// - When `precision == FIXED_PRECISION`, every bit of the raw value is significant and
///   the check passes trivially (no "extra" bits to validate).

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fix the source of the raw value: scale it to the declared precision (multiply/divide by the correct power of 10) before constructing the fixed-point type.
  2. Verify the precision passed to the constructor matches the data's actual decimal places; do not force a smaller precision onto finer-grained data.
  3. If reading persisted data, check whether it was written with a different precision and re-migrate the data.
  4. Audit any manual `.raw` arithmetic in your code and use the domain type constructors/`Decimal` conversions instead.

Example fix

// before
let price = Price::new_checked(raw_int, 2)?; // raw_int = 1234567, not a multiple of 100

// after
let scaled = raw_int / 1000 * 100; // or rescale correctly upstream
let price = Price::new_checked(scaled, 2)?;
Defensive patterns

Strategy: validation

Validate before calling

def raw_is_exact(raw: int, precision: int) -> bool:
    scale = 10 ** precision
    return raw % scale == 0

Try / catch

try:
    price = Price::new_checked(raw, precision)
except Exception:
    # rescale or reject the raw value before retrying
    raise

Prevention

When it happens

Trigger: Constructing a fixed-point type (Price, Quantity, Money, etc.) from a raw integer whose last digits are not zero-filled to the scale — e.g. building `Price` from raw=1234567 with precision 2/scale 100 — or reading such a value from corrupted data, wrong endianness decoding, or multiplying a raw value without rescaling.

Common situations: Feeding raw exchange integers with more decimal digits than the declared precision; manual arithmetic on `.raw` values that breaks the fixed-point invariant; deserializing data written with a different precision; scaling errors when converting floats to raw via the wrong factor (x1000 vs x100).

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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