BoundaryML/baml · error

invalid SHA-256 checksum `{hash}`

Error message

invalid SHA-256 checksum `{hash}`

What it means

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.

Source

Thrown at baml_language/crates/baml_release/src/lib.rs:342

pub fn release_archive_url_for_repo(
    product: Product,
    version: &str,
    target: &str,
    repo: &str,
) -> String {
    format!(
        "https://github.com/{repo}/releases/download/{}-{version}/{}",
        product.tag_prefix(),
        release_archive_filename(product, version, target)
    )
}

pub fn validate_sha256(hash: &str) -> Result<String> {
    if hash.len() == 64 && hash.chars().all(|c| c.is_ascii_hexdigit()) {
        Ok(hash.to_ascii_lowercase())
    } else {
        anyhow::bail!("invalid SHA-256 checksum `{hash}`")
    }
}

pub fn verify_release_archive_checksum_text(
    archive_bytes: &[u8],
    archive_url: &str,
    checksum_text: &str,
) -> Result<(), FetchError> {
    let archive_name = archive_url.rsplit('/').next().unwrap_or(archive_url);
    let expected = parse_release_checksum(checksum_text, archive_name).map_err(|_| {
        FetchError::BinaryNotInArchive {
            name: archive_name.to_string(),
        }
    })?;
    let got = format!("{:x}", Sha256::digest(archive_bytes));
    compare_sha256(archive_url, &expected, &got)
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Copy the full 64-character SHA-256 digest from the official checksum file.
  2. Ensure the value is hex only — strip "sha256:" prefixes, whitespace, and 0x prefixes before passing.
  3. Regenerate the digest with `sha256sum <artifact>` and use that output.
  4. Fix upstream manifest/checksum generation if it emits non-SHA-256 digests.

Example fix

// before
let hash = "sha256:e3b0c44298fc1c14..."; // prefixed
// after
let hash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
validate_sha256(hash)?;
Defensive patterns

Strategy: validation

Validate before calling

fn looks_like_sha256(s: &str) -> bool {
    s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())
}

Type guard

fn is_sha256_hash(s: &str) -> bool { s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/a717596c80b2f62d. Report an issue: GitHub.