jdx/mise · error · RuntimeError

# : malformed sha256

Error message

#{context}: malformed sha256

What it means

A Ruby raise in the brew shim's fetch: the supplied sha256 is not exactly 64 lowercase hexadecimal characters. The shim normalizes (strip/downcase) and validates the digest format before using it as a cache key and integrity check.

Solutions

  1. Recompute the digest with `shasum -a 256` (SHA-256, 64 hex chars) and correct the package definition
  2. Remove any prefixes/suffixes/quotes around the digest
  3. Ensure the value is a plain string of 64 hex characters
  4. If the artifact changed upstream, re-pin a new legitimate digest

Example fix

# before
sha256 = "d41d8cd98f00b204e9800998ecf8427e"  # md5
# after
sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
Defensive patterns

Strategy: validation

Validate before calling

unless sha256.to_s.match?(/\A[0-9a-fA-F]{64}\z/)
  raise "#{context}: sha256 must be 64 hex chars"
end

Type guard

def sha256?(s) = s.to_s.match?(/\A[0-9a-f]{64}\z/)

Try / catch

begin
  MiseDownload.fetch(url, sha256, context)
rescue RuntimeError => e
  abort "bad checksum for #{context}: #{e.message}"
end

Prevention

When it happens

Trigger: Passing a truncated digest, an MD5/SHA-1 hash, a digest with '0x' prefix or stray characters, or a non-string object whose to_s isn't a hex string to fetch (or cc/cxx which delegate to fetch).

Common situations: Copy-paste errors from terminal output (wrong hash algorithm column), digests from `md5sum` instead of `shasum -a 256`, formulas with corrupted checksum fields.

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 jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/4058c4c46f7c2abd. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/brew/shim.rb:74

  $stderr.puts "Error: #{message}"
  exit 1
end

class ShimUnsupportedError < StandardError; end

def shim_unsupported!(feature)
  raise ShimUnsupportedError,
        "formula uses `#{feature}`, which mise's source-build shim does not support"
end

module MiseDownload
  module_function

  # 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

View on GitHub (pinned to 533346cc37)