jdx/mise · error · RuntimeError

#{context}: malformed sha256

Error message

#{context}: malformed sha256

What it means

MiseDownload.fetch validates that the provided sha256 is a 64-character lowercase hexadecimal string before use. A digest of the wrong length or containing non-hex characters (e.g. truncated, uppercase, an MD5 hash, or a 'sha256:' prefixed value) fails this regex check and raises.

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 afd2eddd3a)

Solutions

  1. Recompute the digest with sha256sum and paste the full 64-hex-character value.
  2. Strip any 'sha256:'/'SHA256=' prefix and convert uppercase hex to lowercase.
  3. Verify the field isn't an md5/sha1 value (32/40 chars) — replace it with an actual sha256.

Example fix

// before
sha256 = "ABCDEF1234567890"
// after
sha256 = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
Defensive patterns

Strategy: validation

Validate before calling

# ruby format check before calling fetch
sha256 = sha256.to_s.strip.downcase
raise "bad sha256 format" unless sha256.match?(/\A[0-9a-f]{64}\z/)

Try / catch

begin
  MiseDownload.fetch(url, sha256, context)
rescue RuntimeError => e
  raise unless e.message.include?("malformed sha256")
  # recompute and retry with a corrected digest
end

Prevention

When it happens

Trigger: fetch called with a sha256 that is not exactly 64 hex chars — e.g. a 32-char MD5, a base64 digest, 'SHA256:abc...', or a copy with truncation/whitespace artifacts.

Common situations: Copying the wrong hash column from a checksums file; pasting from output that prefixes the algorithm name; truncating the digest when editing configs by hand.

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