nautechsystems/nautilus_trader · error · anyhow::Error
Failed to parse decimal '{value}': {e}
Error message
Failed to parse decimal '{value}': {e} What it means
parse_decimal converts a Kraken API string into a fixed-precision Decimal; this error is raised when the string fails Decimal::parse. Empty strings and "0" are normalized to 0 beforehand, so the failure means the exchange returned a value the parser cannot interpret. It is a data-format error, not an arithmetic error.
Source
Thrown at crates/adapters/kraken/src/common/parse.rs:60
enums::{
KrakenFuturesOrderEventType, KrakenInstrumentType, KrakenPositionSide,
KrakenSpotTrigger, KrakenTriggerSignal,
},
},
http::models::{
AssetPairInfo, FuturesFill, FuturesInstrument, FuturesOpenOrder, FuturesOrderEvent,
FuturesPosition, FuturesPublicExecution, OhlcData, SpotOrder, SpotTrade,
},
};
/// Parse a decimal string, handling empty strings and "0" values.
pub fn parse_decimal(value: &str) -> anyhow::Result<Decimal> {
if value.is_empty() || value == "0" {
return Ok(dec!(0));
}
value
.parse::<Decimal>()
.map_err(|e| anyhow::anyhow!("Failed to parse decimal '{value}': {e}"))
}
fn parse_rfc3339_timestamp(value: &str, field: &str) -> anyhow::Result<UnixNanos> {
value
.parse::<UnixNanos>()
.map_err(|e| anyhow::anyhow!("Failed to parse {field}='{value}': {e}"))
}
/// Normalizes a Kraken currency code by stripping the legacy X/Z prefix.
///
/// Kraken uses legacy prefixes for some currencies (e.g., XXBT for Bitcoin, XETH for Ethereum,
/// ZUSD for USD). This function strips those prefixes for consistent lookups.
#[inline]
pub fn normalize_currency_code(code: &str) -> &str {
code.strip_prefix("X")
.or_else(|| code.strip_prefix("Z"))
.unwrap_or(code)
}View on GitHub (pinned to 18893faf8b)
Solutions
- Log and inspect the offending raw value to confirm the exact format Kraken returned.
- Normalize the input (strip thousands separators, expand scientific notation) before calling parse_decimal.
- Use parse_decimal_opt and treat unparseable values as absent rather than failing the whole message.
- Update the adapter if a Kraken API format change is the cause.
Example fix
// before
let qty = parse_decimal(fill["vol"])?;
// after
let qty = match parse_decimal_opt(fill["vol"]) {
Some(d) if d > dec!(0) => d,
_ => { tracing::warn!(raw = %fill["vol"], "unparseable fill volume, skipping"); return Ok(None); }
}; Defensive patterns
Strategy: validation
Validate before calling
// Rust: pre-validate exchange numeric strings
fn is_parseable_decimal(s: &str) -> bool {
!s.is_empty() && s != "0" && s.parse::<rust_decimal::Decimal>().is_ok()
} Try / catch
match parse_decimal(raw) {
Ok(d) => d,
Err(e) => { tracing::warn!("bad decimal {e}; skipping record"); return Ok(None); }
} Prevention
- Use parse_decimal_opt for optional or best-effort fields.
- Log the raw value on failure to detect exchange format drift early.
- Normalize locale separators and scientific notation before parsing.
- Add integration fixtures for real Kraken payloads.
When it happens
Trigger: parse_decimal receiving a non-numeric or badly formatted string (e.g. "1,234.5", "12.3.4", "NaN", locale-formatted values) from parse_decimal_opt, compute_avg_px, or parse_fill_report.
Common situations: Kraken changing a field's format or emitting null-ish placeholders; a caller passing already-localized strings; SDK/API version drift where a field switched from number-string to scientific notation.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid {field} `{raw}`
- Unsupported Kraken OHLC interval: {interval}
- invalid signed E18 integer for {field}: {value}
- invalid {field}='{raw}': {e}
- Invalid multiplier {}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a9c78c581957f46e.
Report an issue: GitHub.