{"record":{"id":"90b052ea2ee615ce","repo":"nautechsystems/nautilus_trader","slug":"replacement-scan-cursor-base-fee-is-invalid","errorCode":null,"errorMessage":"Replacement scan cursor base fee is invalid","messagePattern":"Replacement scan cursor base fee is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":6224,"sourceCode":"        .await\n        .context(\"failed to load replacement scan cursor\")?;\n        row.map(\n            |(number, hash, parent_hash, timestamp, base_fee, stored_digest)| {\n                anyhow::ensure!(\n                    stored_digest == manifest_digest,\n                    \"Replacement scan manifest identity changed\"\n                );\n                Ok(ExecutionVerifiedHeader {\n                    number: u64::try_from(number)\n                        .context(\"Replacement scan cursor number is negative\")?,\n                    hash,\n                    parent_hash,\n                    timestamp: u64::try_from(timestamp)\n                        .context(\"Replacement scan cursor timestamp is negative\")?,\n                    base_fee_per_gas: base_fee\n                        .map(|value| {\n                            value.parse::<u128>().map_err(|_| {\n                                anyhow::anyhow!(\"Replacement scan cursor base fee is invalid\")\n                            })\n                        })\n                        .transpose()?,\n                })\n            },\n        )\n        .transpose()\n    }\n\n    pub(crate) async fn record_execution_replacement_scan(\n        &self,\n        scan: &ExecutionReplacementScan<'_>,\n    ) -> anyhow::Result<()> {\n        anyhow::ensure!(\n            !scan.decisions.is_empty()\n                && scan.provider_ids.len() == 3\n                && scan.operator_ids.len() == 3\n                && scan.failure_domain_ids.len() >= 3,","sourceCodeStart":6206,"sourceCodeEnd":6242,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L6206-L6242","documentation":"Data-integrity check when loading the replacement scan cursor: the stored cursor row's base_fee column decoded to a negative value, which is not a valid EIP-1559 base fee, so the cursor is rejected as corrupt.","triggerScenarios":"load_execution_replacement_cursor reads a non-empty base_fee_per_gas string that fails `value.parse::<u128>()` — e.g. hex-encoded, empty string, scientific notation, or truncated text.","commonSituations":"A writer stored the fee in hex or with 0x prefix; value exceeded u128 range; manual row edits; schema drift where the column holds a different encoding.","solutions":["Inspect the stored base_fee_per_gas string and correct or delete the row","Fix the writer to store base fee as a canonical decimal u128 string","Re-run the replacement scan to record a fresh cursor","If the value can legitimately exceed u128, widen the parse/format"],"exampleFix":"// before\nanyhow::anyhow!(\"Replacement scan cursor base fee is invalid\")\n// after\nanyhow::anyhow!(\"Replacement scan cursor base fee is invalid: {value}\") // log the offending value to diagnose hex vs decimal corruption","handlingStrategy":"validation","validationCode":"fn parse_base_fee(s: &str) -> anyhow::Result<u128> {\n    let v = s.parse::<u128>()\n        .map_err(|e| anyhow::anyhow!(\"base fee {s:?} not decimal u128: {e}\"))?;\n    Ok(v)\n}","typeGuard":"fn is_decimal_u128(s: &str) -> bool {\n    !s.is_empty() && s.bytes().all(|b| b.is_ascii_digit()) && s.parse::<u128>().is_ok()\n}","tryCatchPattern":"match db.load_execution_replacement_cursor(..).await {\n    Err(e) if e.to_string().contains(\"base fee is invalid\") => {\n        // row corrupt: delete and re-record scan\n    }\n    other => other,\n}","preventionTips":["Always serialize base fee as canonical decimal string (no 0x, no exponent)","Round-trip test the writer/reader format for base fee","Include the offending value in the error message when editing the source"],"tags":["parsing","base-fee","data-corruption","database"],"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-14T00:17:10.932Z"}