jdx/mise · error

Invalid lockfile checksum for precompiled Erlang/OTP

Error message

Invalid lockfile checksum for precompiled Erlang/OTP {version}; regenerate mise.lock with `mise lock`

What it means

require_locked_precompiled_checksum validates the checksum stored in mise.lock for a precompiled Erlang install. The checksum must match `sha256:` followed by 64 hex chars; anything else means the lockfile entry is stale or malformed.

Solutions

  1. Regenerate the lockfile by running `mise lock` as the message instructs
  2. Remove merge-conflict markers or hand edits from mise.lock and re-lock
  3. Upgrade mise so lockfile reading matches the format written by your version

Example fix

# before (mise.lock)
[erlang.26.2.5]
checksum = "abc123"

# after: run `mise lock`
# checksum = "sha256:64hexchars..."
Defensive patterns

Strategy: validation

Validate before calling

grep -E 'checksum\s*=\s*"sha256:[0-9a-f]{64}"' mise.lock || mise lock

Try / catch

mise install erlang@X || { mise lock && mise install erlang@X; }

Prevention

When it happens

Trigger: Installing precompiled Erlang in locked mode where the mise.lock checksum entry exists but does not match the expected `sha256:<64 hex>` format (old mise version wrote a different format, hand-edited lockfile, merge conflict residue).

Common situations: mise.lock generated by an older mise before checksum format changes, manual edits, or git merge conflicts left in mise.lock.

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/50115d15b868dfbc. Report an issue: GitHub.

Appendix: source

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

    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`"
        );
    }

    Ok(checksum.to_string())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_hex_build_checksum_requires_exact_publisher_record() {
        let builds = "OTP-28.5.0.4 abc 2026-07-27T13:55:40Z 34498e6287e1fbc31250d36dd88bcdb1d286cedbdd9b1a66bbc4284738d2d2eb\n\
                      OTP-28.5.0.5 def 2026-08-04T10:35:03Z e3476633cae6fef8e1bb53576832b15823f715e70e3d4d1e66a6be908804f967\n";

        assert_eq!(
            parse_hex_build_checksum(builds, "OTP-28.5.0.5").unwrap(),

View on GitHub (pinned to 533346cc37)