{"record":{"id":"bcaf1d6e16629481","repo":"nautechsystems/nautilus_trader","slug":"invalid-timestamp-ts-e","errorCode":null,"errorMessage":"Invalid timestamp '{ts}': {e}","messagePattern":"Invalid timestamp '(.+?)': (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/websocket/parse.rs","lineNumber":47,"sourceCode":"    types::{Price, Quantity},\n};\nuse rust_decimal::Decimal;\nuse serde::Serialize;\n\nuse super::messages::{\n    PolymarketBestBidAsk, PolymarketBookLevel, PolymarketBookSnapshot, PolymarketQuote,\n    PolymarketTrade,\n};\nuse crate::common::{\n    enums::PolymarketOrderSide,\n    parse::{determine_trade_id, parse_decimal_exact},\n};\n\n/// Parses a millisecond epoch timestamp string into [`UnixNanos`].\npub fn parse_timestamp_ms(ts: &str) -> anyhow::Result<UnixNanos> {\n    let ms: u64 = ts\n        .parse()\n        .map_err(|e| anyhow::anyhow!(\"Invalid timestamp '{ts}': {e}\"))?;\n    let ns = ms\n        .checked_mul(NANOSECONDS_IN_MILLISECOND)\n        .ok_or_else(|| anyhow::anyhow!(\"Timestamp overflow for '{ts}'\"))?;\n    Ok(UnixNanos::from(ns))\n}\n\npub(crate) fn parse_price(s: &str, precision: u8) -> CorrectnessResult<Price> {\n    let value = parse_decimal_exact(s).map_err(|e| CorrectnessError::PredicateViolation {\n        message: format!(\"Invalid price '{s}': {e}\"),\n    })?;\n    Price::from_decimal_dp(value, precision)\n}\n\npub(crate) fn parse_quantity(s: &str, precision: u8) -> CorrectnessResult<Quantity> {\n    let value = parse_decimal_exact(s).map_err(|e| CorrectnessError::PredicateViolation {\n        message: format!(\"Invalid quantity '{s}': {e}\"),\n    })?;\n    Quantity::from_decimal_dp(value, precision)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/websocket/parse.rs#L29-L65","documentation":"parse_timestamp_ms converts a millisecond epoch string from Polymarket messages into a UnixNanos value. If the string cannot be parsed as a u64 (non-numeric, empty, or containing invalid characters), the function wraps the std parse error in an anyhow error with the offending input.","triggerScenarios":"Calling parse_timestamp_ms with a string that is not a valid u64: empty string, \"2024-01-15T10:00:00Z\" (ISO format), \"1699999999999.5\" (float), or a field that is null/missing stringified.","commonSituations":"Polymarket changing the timestamp field format; passing an ISO-8601 datetime instead of epoch millis; unit tests feeding mock payloads with wrong timestamp encodings.","solutions":["Log/inspect the ts string from the error message — it names the exact invalid value","Convert ISO-8601 timestamps to epoch milliseconds before calling (e.g. via chrono)","Truncate or reject float timestamps: parse as f64 then cast, or strip fractional part","Update the adapter parsing if Polymarket changed the field format"],"exampleFix":"// before: parse_timestamp_ms(\"2024-01-15T10:00:00Z\") fails\nlet ts = parse_timestamp_ms(msg.timestamp)?;\n// after: normalize ISO timestamps to epoch millis first\nlet ms = if msg.timestamp.contains('-') {\n    chrono::DateTime::parse_from_rfc3339(&msg.timestamp)\n        .map_err(|e| anyhow::anyhow!(\"bad ts: {e}\"))?\n        .timestamp_millis()\n        .to_string()\n} else {\n    msg.timestamp.clone()\n};\nlet ts = parse_timestamp_ms(&ms)?;","handlingStrategy":"validation","validationCode":"fn is_epoch_millis(s: &str) -> bool {\n    !s.is_empty() && s.bytes().all(|b| b.is_ascii_digit()) && s.len() <= 13\n}","typeGuard":"fn as_epoch_millis(raw: &str) -> Option<u64> { raw.parse::<u64>().ok() }","tryCatchPattern":"match parse_timestamp_ms(ts) {\n    Ok(nanos) => /* proceed */,\n    Err(e) if e.to_string().contains(\"Invalid timestamp\") => {\n        log::warn!(\"dropping message with bad timestamp: {e}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Pass epoch milliseconds, never ISO-8601 strings or floats","Normalize timestamp format at message-decode time","Check the venue schema before assuming the timestamp format"],"tags":["polymarket","timestamp","parsing"],"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"}