jdx/mise · error · RuntimeError
#{context}: sha256 mismatch (expected #{sha256}, got #{actua
Error message
#{context}: sha256 mismatch (expected #{sha256}, got #{actual}) What it means
After downloading an artifact to a temp file, MiseDownload.fetch hashes it and compares against the expected sha256. On mismatch the temp file is deleted and this error is raised, protecting against corrupted, truncated, or tampered downloads; artifacts are only promoted into the content-addressed cache when the digest matches.
Source
Thrown at src/system/packages/brew/shim.rb:87
# download with redirects into the cache, verify, return the path
def fetch(url, sha256, context)
raise "#{context}: missing sha256" if sha256.to_s.strip.empty?
sha256 = sha256.to_s.strip.downcase
raise "#{context}: malformed sha256" unless sha256.match?(/\A[0-9a-f]{64}\z/)
MISE_BREW_CACHE.mkpath
dest = MISE_BREW_CACHE + "#{sha256}--#{File.basename(URI(url).path)}"
unless dest.file? && Digest::SHA256.file(dest).hexdigest == sha256
ohai "Downloading #{url}"
tmp = Pathname.new("#{dest}.incomplete")
URI.open(url, "rb", redirect: true) do |remote|
tmp.open("wb") { |f| IO.copy_stream(remote, f) }
end
actual = Digest::SHA256.file(tmp).hexdigest
if actual != sha256
tmp.unlink
raise "#{context}: sha256 mismatch (expected #{sha256}, got #{actual})"
end
tmp.rename(dest)
end
dest
end
# unpack an archive the way brew stages sources: if the archive contains a
# single top-level directory, its contents become the stage root
def unpack(archive, dest)
dest.mkpath
case archive.basename.to_s
when /\.(tar\.(gz|xz|bz2|zst)|tgz|txz|tbz2?|tar|crate)\z/i
system_or_die "tar", "xf", archive.to_s, "-C", dest.to_s
when /\.zip\z/i
system_or_die "unzip", "-qo", archive.to_s, "-d", dest.to_s
when /\.(gz|xz|bz2)\z/i
data = `#{archive.to_s =~ /xz\z/ ? "xz -dc" : archive.to_s =~ /bz2\z/ ? "bzip2 -dc" : "gzip -dc"} #{Shellwords.escape(archive.to_s)}`
raise "failed to decompress #{archive}" unless $?.success?View on GitHub (pinned to afd2eddd3a)
Solutions
- Verify the url and sha256 belong to the exact same artifact/version; recompute sha256sum on a fresh download.
- Retry the download — transient truncation can be resolved by clearing the cache entry and fetching again.
- Pin a specific immutable version instead of a moving/moving-tag URL so the checksum stays valid.
- Check for proxies/antivirus altering responses (curl the URL and compare hashes); bypass or trust the proxy.
- If upstream re-released the artifact, update the recipe's checksum to the new verified digest.
Example fix
// before
MiseDownload.fetch("https://example.com/tool-1.2.tar.gz", "aaa...old...", "tool")
// after (recomputed for the actual artifact)
MiseDownload.fetch("https://example.com/tool-1.2.tar.gz", "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "tool") Defensive patterns
Strategy: validation
Validate before calling
# verify checksum outside the shim first curl -fsSL "$url" -o /tmp/artifact && echo "$sha256 /tmp/artifact" | sha256sum -c -
Try / catch
begin
path = MiseDownload.fetch(url, sha256, context)
rescue RuntimeError => e
raise unless e.message.include?("sha256 mismatch")
# re-download, verify upstream checksums, or update the pinned digest
end Prevention
- Pin immutable versioned URLs, never moving tags, so checksums stay valid.
- Take digests from upstream published checksum files, not hand transcription.
- Investigate proxies/AV if mismatches recur on the same network.
- When upstream re-releases, re-verify and update the checksum deliberately.
When it happens
Trigger: The downloaded file at url does not hash to the declared sha256 — wrong URL for the checksum, upstream re-uploaded/changed the artifact, a truncated or MITM-corrupted download, or a checksum copied for a different version.
Common situations: Mirror/proxy serving stale files; release artifacts replaced after publication (moving tags); corporate proxies injecting error pages; typos in the checksum after manual entry; downloading 'latest' while the checksum pins an older build.
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
- {name}: sha256 is {actual}, the packslip says {}
- #{context}: missing sha256
- #{context}: malformed sha256
- brew-cask:{}: cask metadata has no sha256
- remote cache blob failed digest verification
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/82240e9f4272fe5f.
Report an issue: GitHub.