{"record":{"id":"077e5cb38b23bde3","repo":"nautechsystems/nautilus_trader","slug":"invalid-block-timestamp-block-timestamp-e","errorCode":null,"errorMessage":"Invalid block timestamp '{block_timestamp}': {e}","messagePattern":"Invalid block timestamp '(.+?)': (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":2451,"sourceCode":"                u32::try_from(log_index).with_context(|| \"Pool snapshot log index is negative\")?;\n            let block_hash = if transaction_index == BLOCK_SCOPED_SNAPSHOT_INDEX\n                && log_index == BLOCK_SCOPED_SNAPSHOT_INDEX\n            {\n                Some(transaction_hash.clone())\n            } else {\n                observed_block_hash\n            };\n            let block_timestamp = row\n                .try_get::<Option<String>, _>(\"block_timestamp\")?\n                .ok_or_else(|| {\n                    anyhow::anyhow!(\n                        \"Missing block timestamp for pool snapshot {} at block {}\",\n                        pool_identifier,\n                        block\n                    )\n                })?;\n            let timestamp = parse_cached_block_timestamp(&block_timestamp)\n                .map_err(|e| anyhow::anyhow!(\"Invalid block timestamp '{block_timestamp}': {e}\"))?;\n\n            let block_position =\n                BlockPosition::new(block, transaction_hash, transaction_index, log_index)\n                    .with_block_hash(block_hash);\n\n            let fee_protocol_value = row.get::<i16, _>(\"fee_protocol\");\n            let fee_protocol = u8::try_from(fee_protocol_value).with_context(|| {\n                format!(\"Invalid pool snapshot fee protocol {fee_protocol_value}\")\n            })?;\n            let fee_protocol0_basis_points = row\n                .get::<Option<i32>, _>(\"fee_protocol0_basis_points\")\n                .map(|value| {\n                    u32::try_from(value).with_context(|| {\n                        format!(\"Invalid token0 fee protocol basis points {value}\")\n                    })\n                })\n                .transpose()?;\n            let fee_protocol1_basis_points = row","sourceCodeStart":2433,"sourceCodeEnd":2469,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L2433-L2469","documentation":"The snapshot row's `block_timestamp` string exists but could not be parsed into a timestamp by `parse_cached_block_timestamp`. The library stores timestamps as strings in a canonical format; any deviation (wrong format, garbage, empty string) makes the cached snapshot unusable because the block time cannot be reconstructed.","triggerScenarios":"A `block_timestamp` value stored in a format different from what `parse_cached_block_timestamp` expects (e.g. epoch integer string vs ISO-8601, or a locale-dependent format), written by a different adapter version or an external tool that populated the column.","commonSituations":"Mixed adapter versions writing the same table with different timestamp formats; manual row edits; an ETL/backfill script that inserted Unix epoch seconds where RFC3339 was expected; timezone formatting differences.","solutions":["Check the exact string in the offending row and rewrite it in the canonical format expected by `parse_cached_block_timestamp`.","Re-snapshot the affected pools so rows are rewritten by the current adapter version.","Standardize the writer: confirm the persist path formats timestamps the same way the parser expects (round-trip test).","Normalize legacy rows with an UPDATE converting the old format to the canonical one."],"exampleFix":"// before: writing epoch string\nrow.bind(\"block_timestamp\", block.timestamp.to_string());\n// after: write canonical parseable format\nrow.bind(\"block_timestamp\", chrono::DateTime::from_timestamp(block.timestamp as i64, 0)\n    .unwrap().to_rfc3339());","handlingStrategy":"validation","validationCode":"let ts: String = row_ts;\nlet parsed = chrono::DateTime::parse_from_rfc3339(&ts);\nif parsed.is_err() {\n    // normalize or reject before loading\n    eprintln!(\"non-canonical block_timestamp: {ts}\");\n}","typeGuard":"fn is_canonical_timestamp(s: &str) -> bool {\n    chrono::DateTime::parse_from_rfc3339(s).is_ok()\n}","tryCatchPattern":"match load_snapshot(...).await {\n    Err(e) if e.to_string().contains(\"Invalid block timestamp\") => {\n        re_snapshot_pool(pool_id).await // rewrite the row via the writer\n    }\n    other => other,\n}","preventionTips":["Always write timestamps with one canonical formatter (e.g. RFC3339) in the persist path.","Add a round-trip unit test: persist a snapshot then load it.","Normalize legacy rows with a migration when changing timestamp format."],"tags":["database","date-parsing","data-integrity","format-mismatch"],"backgroundTag":"invalid-date-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"}