{"record":{"id":"a717596c80b2f62d","repo":"BoundaryML/baml","slug":"invalid-sha-256-checksum-hash","errorCode":null,"errorMessage":"invalid SHA-256 checksum `{hash}`","messagePattern":"invalid SHA-256 checksum `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml_release/src/lib.rs","lineNumber":342,"sourceCode":"\npub fn release_archive_url_for_repo(\n    product: Product,\n    version: &str,\n    target: &str,\n    repo: &str,\n) -> String {\n    format!(\n        \"https://github.com/{repo}/releases/download/{}-{version}/{}\",\n        product.tag_prefix(),\n        release_archive_filename(product, version, target)\n    )\n}\n\npub fn validate_sha256(hash: &str) -> Result<String> {\n    if hash.len() == 64 && hash.chars().all(|c| c.is_ascii_hexdigit()) {\n        Ok(hash.to_ascii_lowercase())\n    } else {\n        anyhow::bail!(\"invalid SHA-256 checksum `{hash}`\")\n    }\n}\n\npub fn verify_release_archive_checksum_text(\n    archive_bytes: &[u8],\n    archive_url: &str,\n    checksum_text: &str,\n) -> Result<(), FetchError> {\n    let archive_name = archive_url.rsplit('/').next().unwrap_or(archive_url);\n    let expected = parse_release_checksum(checksum_text, archive_name).map_err(|_| {\n        FetchError::BinaryNotInArchive {\n            name: archive_name.to_string(),\n        }\n    })?;\n    let got = format!(\"{:x}\", Sha256::digest(archive_bytes));\n    compare_sha256(archive_url, &expected, &got)\n}\n","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml_release/src/lib.rs#L324-L360","documentation":"validate_sha256 checks that a checksum string is exactly 64 ASCII hex digits; if so it returns the lowercased hash, otherwise it bails with \"invalid SHA-256 checksum `{hash}`\". It validates checksums coming from release checksum files, manifests, and SDK metadata before they're used for verification.","triggerScenarios":"Passing a hash that is the wrong length (e.g. truncated by copy-paste, or a SHA-1 40-char hash), or containing non-hex characters (\"0x\" prefixes, whitespace, base64-encoded digests) to validate_sha256 via verify_sha256, parse_release_checksum, validate_artifact, or validate_sdk.","commonSituations":"Hand-editing a manifest and pasting a short/uppercase-mixed/garbage hash; using an MD5 or SHA-1 digest; checksum file line mangled by tooling; trailing newline or label accidentally included.","solutions":["Copy the full 64-character SHA-256 digest from the official checksum file.","Ensure the value is hex only — strip \"sha256:\" prefixes, whitespace, and 0x prefixes before passing.","Regenerate the digest with `sha256sum <artifact>` and use that output.","Fix upstream manifest/checksum generation if it emits non-SHA-256 digests."],"exampleFix":"// before\nlet hash = \"sha256:e3b0c44298fc1c14...\"; // prefixed\n// after\nlet hash = \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\";\nvalidate_sha256(hash)?;","handlingStrategy":"validation","validationCode":"fn looks_like_sha256(s: &str) -> bool {\n    s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())\n}","typeGuard":"fn is_sha256_hash(s: &str) -> bool { s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) }","tryCatchPattern":null,"preventionTips":["Always take hashes from `sha256sum` output or official checksum files.","Strip prefixes (\"sha256:\", \"0x\") and whitespace before validation.","Never store MD5/SHA-1 digests in manifests that require SHA-256."],"tags":["checksum","sha256","validation","manifest"],"backgroundTag":"invalid-argument-format","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}