jdx/mise · error

invalid Hex OTP checksum for

Error message

invalid Hex OTP checksum for {release_tag}: {checksum}

What it means

After locating the Hex OTP build record, parse_hex_build_checksum validates that the checksum field is a 64-character lowercase hex sha256. A malformed or absent-format checksum indicates corrupted or unexpected upstream data, so it bails.

Solutions

  1. Clear the cached Hex builds data and retry so a fresh file is fetched
  2. Upgrade mise in case the parser needs updating for a new upstream format
  3. Manually verify the Hex builds file for the release and report upstream corruption
Defensive patterns

Strategy: retry

Validate before calling

# validate checksum line shape before parsing
grep -E "^OTP-26\.2\.5\s+\S+\s+\S+\s+[0-9a-f]{64}$" builds.txt

Try / catch

mise install erlang@X || { rm -rf ~/.cache/mise/erlang*; mise install erlang@X; }

Prevention

When it happens

Trigger: The matched Hex builds line has a checksum field at index 3 that is not 64 lowercase hex chars (truncated line, different record format, corrupted download).

Common situations: Upstream Hex file format changes, partially cached/corrupted checksum files, or custom-mirrored Hex data with altered columns.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/5efd986fe7cd40fa. Report an issue: GitHub.

Appendix: source

Thrown at src/plugins/core/erlang.rs:827

        .lines()
        .filter_map(|line| {
            let parts = line.split_whitespace().collect::<Vec<_>>();
            (parts.first() == Some(&release_tag)).then_some(parts)
        })
        .collect::<Vec<_>>();

    if matching.len() != 1 {
        bail!(
            "expected exactly one Hex OTP build record for {release_tag}, found {}",
            matching.len()
        );
    }

    let checksum = matching[0]
        .get(3)
        .ok_or_else(|| eyre::eyre!("Hex OTP build record for {release_tag} has no checksum"))?;
    if !regex!(r"^[0-9a-f]{64}$").is_match(checksum) {
        bail!("invalid Hex OTP checksum for {release_tag}: {checksum}");
    }

    Ok(format!("sha256:{checksum}"))
}

#[cfg(any(linux, test))]
fn require_locked_precompiled_checksum(version: &str, checksum: Option<&str>) -> Result<String> {
    let checksum = checksum.ok_or_else(|| {
        eyre::eyre!(
            "No lockfile checksum found for precompiled Erlang/OTP {version}; regenerate mise.lock with `mise lock`"
        )
    })?;
    if !regex!(r"^sha256:[0-9a-f]{64}$").is_match(checksum) {
        bail!(
            "Invalid lockfile checksum for precompiled Erlang/OTP {version}; regenerate mise.lock with `mise lock`"
        );
    }

View on GitHub (pinned to 533346cc37)