jdx/mise · error · RuntimeError

# : missing sha256

Error message

#{context}: missing sha256

What it means

A Ruby raise in the brew shim's fetch: a download was requested without a sha256 checksum. The shim intentionally refuses to fetch (and later verify) artifacts without an explicit checksum, since it enforces supply-chain integrity for compiler toolchain downloads.

Solutions

  1. Add the correct sha256 for the source URL to the package definition
  2. Compute it with `shasum -a 256 <archive>` or `curl -sL <url> | shasum -a 256` and paste the digest
  3. If the source is genuinely unofficial/ephemeral, vendor a pinned artifact with a known digest
  4. Check for whitespace-only values that fail the strip.empty? guard

Example fix

# before
MiseDownload.fetch(url, nil, "llvm")
# after
MiseDownload.fetch(url, "e2b1a4...64hex...", "llvm")
Defensive patterns

Strategy: validation

Validate before calling

raise "missing sha256 for #{context}" if sha256.nil? || sha256.to_s.strip.empty?

Type guard

def valid_sha256?(s)
  s.is_a?(String) && s.match?(/\A[0-9a-fA-F]{64}\z/)
end

Try / catch

begin
  path = MiseDownload.fetch(url, sha256, context)
rescue RuntimeError => e
  warn "skipping #{context}: #{e.message}"
end

Prevention

When it happens

Trigger: Calling fetch (directly or via cc/cxx) with sha256 nil or an empty/whitespace string — e.g. a package definition that omits the sha256 field for a source URL.

Common situations: Hand-written or generated package specs missing checksums; formulas migrated from sources without recorded digests; environment/tooling that strips optional fields.

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/0a3724183e25ced8. Report an issue: GitHub.

Appendix: source

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

def odie(message)
  $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

View on GitHub (pinned to 533346cc37)