{"record":{"id":"00e7dc1473214332","repo":"nautechsystems/nautilus_trader","slug":"chain-checkpoint-hash-must-contain-32-hexadecimal","errorCode":null,"errorMessage":"Chain checkpoint hash must contain 32 hexadecimal bytes","messagePattern":"Chain checkpoint hash must contain 32 hexadecimal bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1219,"sourceCode":"            );\n        }\n    }\n\n    let endpoints = [\n        normalize_endpoint(authoritative_url)?,\n        normalize_endpoint(config.verifiers[0].http_rpc_url.expose_secret())?,\n        normalize_endpoint(config.verifiers[1].http_rpc_url.expose_secret())?,\n    ];\n    ensure_distinct(endpoints.iter().map(String::as_str), \"provider endpoints\")?;\n\n    let anchor = &config.chain_anchor;\n    anyhow::ensure!(anchor.chain_id != 0, \"Chain anchor ID must be nonzero\");\n    anyhow::ensure!(\n        !anchor.chain_name.trim().is_empty(),\n        \"Chain anchor name is required\"\n    );\n    let checkpoint_hash = B256::from_str(&anchor.checkpoint_hash)\n        .map_err(|_| anyhow::anyhow!(\"Chain checkpoint hash must contain 32 hexadecimal bytes\"))?;\n    anyhow::ensure!(\n        checkpoint_hash != B256::ZERO,\n        \"Chain checkpoint hash must be nonzero\"\n    );\n    anyhow::ensure!(\n        anchor.max_head_skew_blocks != 0\n            && anchor.max_head_age_secs != 0\n            && anchor.max_future_drift_secs != 0,\n        \"Chain head skew, age, and future-drift limits must be nonzero\"\n    );\n    anyhow::ensure!(\n        !config.manifest_version.trim().is_empty(),\n        \"Deployment manifest version is required\"\n    );\n    let manifest_digest = B256::from_str(&config.manifest_digest).map_err(|_| {\n        anyhow::anyhow!(\"Deployment manifest digest must contain 32 hexadecimal bytes\")\n    })?;\n    anyhow::ensure!(","sourceCodeStart":1201,"sourceCodeEnd":1237,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1201-L1237","documentation":"`validate_config` parses `config.chain_anchor.checkpoint_hash` with `B256::from_str`, which requires exactly 32 bytes encoded as 64 hex characters (with or without a 0x prefix depending on alloy's parsing). If the string is not valid hex, has the wrong length, or is empty, parsing fails and this error is produced. It precedes the separate nonzero check, so this error is specifically about format, not value.","triggerScenarios":"Configuring `verification.chain_anchor.checkpoint_hash` with a string that fails B256 parsing: fewer/more than 64 hex chars, non-hex characters, empty string, or stray whitespace.","commonSituations":"Copying a truncated hash from terminal output; pasting a base64 or bech32 value instead of hex; including quotes or '0x' handling mistakes; a placeholder like \"<checkpoint-hash>\" left in the template.","solutions":["Replace the value with the full 64-hex-character checkpoint hash (32 bytes) for the target chain.","Fetch the canonical checkpoint from the chain's official sources (e.g. the beacon chain checkpoint sync endpoint) rather than terminal output.","Verify the string contains only hex characters [0-9a-fA-F] and is exactly 64 characters long (optionally 0x-prefixed).","Validate locally with `B256::from_str` or any hex decoder before writing it into the config."],"exampleFix":"// before\ncheckpoint_hash = \"abc123\"\n\n// after\ncheckpoint_hash = \"0x5b3dcd0ad2b0d54afbbc20ff749e0a0f4e5e0bda1a4a2d2a6d3f1c0e9b8a7f6e\"","handlingStrategy":"validation","validationCode":"use alloy_primitives::B256;\nuse std::str::FromStr;\nfn check_checkpoint_hash(anchor: &ChainAnchor) -> Result<(), String> {\n    B256::from_str(&anchor.checkpoint_hash)\n        .map(|_| ())\n        .map_err(|_| \"checkpoint_hash must be 32 bytes of hex (64 hex chars)\".into())\n}","typeGuard":"fn is_b256_hex(s: &str) -> bool {\n    let hex = s.strip_prefix(\"0x\").unwrap_or(s);\n    hex.len() == 64 && hex.chars().all(|c| c.is_ascii_hexdigit())\n}","tryCatchPattern":"match validate_config(&cfg) {\n    Err(e) if e.to_string().contains(\"32 hexadecimal bytes\") => {\n        eprintln!(\"checkpoint_hash malformed (need 64 hex chars): {e}\");\n        std::process::exit(1);\n    }\n    other => other,\n}","preventionTips":["Copy checkpoint hashes from canonical sources in full; never hand-truncate from terminal output.","Add a regex check ^0x?[0-9a-fA-F]{64}$ for hash-like config fields in your config linter.","Sanity-check the parsed value is nonzero too, since format-valid-but-zero hashes are rejected separately."],"tags":["config","validation","hex","blockchain"],"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"}