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

  1. Verify the url and sha256 belong to the exact same artifact/version; recompute sha256sum on a fresh download.
  2. Retry the download — transient truncation can be resolved by clearing the cache entry and fetching again.
  3. Pin a specific immutable version instead of a moving/moving-tag URL so the checksum stays valid.
  4. Check for proxies/antivirus altering responses (curl the URL and compare hashes); bypass or trust the proxy.
  5. 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

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


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/82240e9f4272fe5f. Report an issue: GitHub.