{"record":{"id":"b78c2af9118bc32d","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-field-value-e-b78c2a","errorCode":null,"errorMessage":"Failed to parse {field}='{value}': {e}","messagePattern":"Failed to parse (.+?)='(.+?)': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/common/parse.rs","lineNumber":1313,"sourceCode":"    let parsed = parse_decimal(value, field)?;\n    Price::from_decimal_dp(parsed, precision).with_context(|| {\n        format!(\"Failed to construct Price for {field} with precision {precision}\")\n    })\n}\n\npub(crate) fn parse_quantity_with_precision(\n    value: &str,\n    precision: u8,\n    field: &str,\n) -> anyhow::Result<Quantity> {\n    let parsed = parse_decimal(value, field)?;\n    Quantity::from_decimal_dp(parsed, precision).with_context(|| {\n        format!(\"Failed to construct Quantity for {field} with precision {precision}\")\n    })\n}\n\npub(crate) fn parse_price(value: &str, field: &str) -> anyhow::Result<Price> {\n    Price::from_str(value).map_err(|e| anyhow::anyhow!(\"Failed to parse {field}='{value}': {e}\"))\n}\n\npub(crate) fn parse_quantity(value: &str, field: &str) -> anyhow::Result<Quantity> {\n    Quantity::from_str(value).map_err(|e| anyhow::anyhow!(\"Failed to parse {field}='{value}': {e}\"))\n}\n\npub(crate) fn parse_decimal(value: &str, field: &str) -> anyhow::Result<Decimal> {\n    Decimal::from_str(value)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse {field}='{value}' as Decimal: {e}\"))\n}\n\npub(crate) fn parse_millis_timestamp(value: &str, field: &str) -> anyhow::Result<UnixNanos> {\n    let millis: u64 = value\n        .parse()\n        .with_context(|| format!(\"Failed to parse {field}='{value}' as u64 millis\"))?;\n    let nanos = millis\n        .checked_mul(NANOSECONDS_IN_MILLISECOND)\n        .context(\"millisecond timestamp overflowed when converting to nanoseconds\")?;","sourceCodeStart":1295,"sourceCodeEnd":1331,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/common/parse.rs#L1295-L1331","documentation":"parse_price converts a raw exchange string (e.g. an instrument's tick size or lot size filter) into a Nautilus Price via Price::from_str. This error wraps the underlying parse failure and embeds the field name, raw value, and the reason, so instrument parsing can pinpoint which price-like field was malformed.","triggerScenarios":"parse_spot_instrument / parse_linear_instrument / parse_inverse_instrument / parse_option_instrument / extract_strike_from_symbol call parse_price with a value that Price::from_str rejects (non-numeric, empty, out-of-range, or bad precision).","commonSituations":"Bybit returning empty strings for optional fields (e.g. unset tick size); localization/formatting surprises; mocking fixtures with placeholder values; API schema changes moving fields so wrong values get passed as prices.","solutions":["Check the raw instrument payload for the named field and confirm it is a valid decimal number string.","Treat empty strings as absent: skip/None instead of calling parse_price.","Trim whitespace and normalize the string (no commas, thousands separators, or exponent notation if unsupported) before parsing.","Update fixtures/adapter if the Bybit response schema changed."],"exampleFix":"// before\nlet tick = parse_price(&filter.tick_size, \"tick_size\")?;\n// after\nlet tick = (!filter.tick_size.is_empty())\n    .then(|| parse_price(filter.tick_size.trim(), \"tick_size\"))\n    .transpose()?;","handlingStrategy":"validation","validationCode":"// Rust: validate price strings before parse_price\nfn valid_price(s: &str) -> bool {\n    let t = s.trim();\n    !t.is_empty() && t.parse::<f64>().map(|v| v.is_finite() && v > 0.0).unwrap_or(false)\n}","typeGuard":"fn parseable_price(s: &str) -> Option<rust_decimal::Decimal> {\n    let t = s.trim();\n    if t.is_empty() { return None; }\n    t.parse::<rust_decimal::Decimal>().ok()\n}","tryCatchPattern":"let price = parse_price(value, \"tick_size\")\n    .with_context(|| format!(\"instrument {} had bad tick_size\", symbol))?;","preventionTips":["Never pass empty strings for optional price fields; use Option/skip","Trim and strip formatting (commas, whitespace) from exchange strings","Keep instrument fixtures copied from real exchange responses"],"tags":["parsing","price","instrument","bybit"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}