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
- 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.
- Verify the precision passed to the constructor matches the data's actual decimal places; do not force a smaller precision onto finer-grained data.
- If reading persisted data, check whether it was written with a different precision and re-migrate the data.
- 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
- Never perform manual arithmetic on .raw values without rescaling
- Confirm exchange data's decimal places match the declared precision
- Use Decimal/domain constructors instead of raw integer math
- Validate raw values against the fixed-point invariant at ingestion boundaries
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
- Failed to scale continuous-future adjustment to fixed precis
- Instrument not found in cache: {symbol}
- Close command should not be drained
- Flush command should not be drained
- Order invariant violated: first event must be OrderInitializ
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/51f834192ee9640c.
Report an issue: GitHub.