nautechsystems/nautilus_trader · error
invalid candle volume: {e}
Error message
invalid candle volume: {e} What it means
parse_candle_bar converts a Lighter historical candle into a Nautilus Bar. The raw candle's volume must be sign-positive and quantizable to the bar type's size precision; if Quantity::from_decimal_dp fails (or volume is negative, caught by the preceding ensure), this error wraps the underlying precision/conversion failure. It prevents constructing a Bar with an unrepresentable volume.
Source
Thrown at crates/adapters/lighter/src/http/parse.rs:228
let ts_event = parse_millis_to_nanos(timestamp_ms)?;
let price_precision = instrument.price_precision();
let size_precision = instrument.size_precision();
let open = Price::from_decimal_dp(candle.open, price_precision)
.map_err(|e| anyhow::anyhow!("invalid candle open: {e}"))?;
let high = Price::from_decimal_dp(candle.high, price_precision)
.map_err(|e| anyhow::anyhow!("invalid candle high: {e}"))?;
let low = Price::from_decimal_dp(candle.low, price_precision)
.map_err(|e| anyhow::anyhow!("invalid candle low: {e}"))?;
let close = Price::from_decimal_dp(candle.close, price_precision)
.map_err(|e| anyhow::anyhow!("invalid candle close: {e}"))?;
anyhow::ensure!(
candle.volume_base.is_sign_positive(),
"negative candle volume `{}`",
candle.volume_base,
);
let volume = Quantity::from_decimal_dp(candle.volume_base, size_precision)
.map_err(|e| anyhow::anyhow!("invalid candle volume: {e}"))?;
Bar::new_checked(bar_type, open, high, low, close, volume, ts_event, ts_init)
.context("failed to construct Bar from Lighter candle")
}
/// Parses a Lighter historical funding row into a Nautilus [`FundingRateUpdate`].
///
/// Lighter returns `rate` as a magnitude and `direction` as the side paying
/// the funding. Nautilus uses the conventional signed rate: positive when
/// longs pay shorts and negative when shorts pay longs.
///
/// # Errors
///
/// Returns an error if the timestamp cannot be converted.
pub fn parse_funding_rate_update(
funding: &LighterFunding,
instrument_id: InstrumentId,
interval: Option<u16>,View on GitHub (pinned to 18893faf8b)
Solutions
- Set the bar type's size_precision to at least the decimal places the venue reports for volume (Lighter's supported_volume_decimals).
- Pre-normalize candle volume with Decimal rounding to size_precision before parsing.
- Check the candle payload for negative or malformed volume values before parsing.
- Inspect the inner message from Quantity::from_decimal_dp in the wrapped {e} to see the exact precision failure.
Example fix
// before
let bar_type = BarType::new(instrument_id, aggregator, PriceType::Last); // size_precision=2
// after
let bar_type = BarType::new(
instrument_id,
aggregator,
PriceType::Last,
);
// ensure aggregator's size_precision >= venue volume decimals (e.g. 6 for Lighter) Defensive patterns
Strategy: validation
Validate before calling
// Rust: validate candle before parse_candle_bar
if !candle.volume_base.is_sign_positive() {
return Err(anyhow!("skip candle: negative volume {}", candle.volume_base));
}
let dp = candle.volume_base.fract().scale() as u32;
anyhow::ensure!(dp <= size_precision as u32, "volume dp {} > size_precision {}", dp, size_precision); Try / catch
match parse_candle_bar(&bar_type, &candle, size_precision) {
Ok(bar) => bar,
Err(e) => { warn!("skipping candle: {e:#}"); continue; }
} Prevention
- Set bar type size_precision to match Lighter supported_size_decimals.
- Reject candles with non-positive volume upstream.
- Unit-test parsing against the fixture with edge-case volumes.
When it happens
Trigger: Parsing a /candles response whose candle has negative volume_base, or whose volume requires more decimal places than the bar type's size_precision supports (e.g. volume 1.00000005 with size_precision=4), causing from_decimal_dp rounding/precision rejection.
Common situations: Bar type built with too-coarse size_precision for the venue's quote volumes; malformed or adversarial candle data from the HTTP API; copying volumes from a different market with higher precision.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- invalid Futures trade id {}: {e}
- invalid open price: {e}
- invalid high price: {e}
- invalid low price: {e}
- invalid close price: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/214bada5c18c90bb.
Report an issue: GitHub.