{"record":{"id":"4058c4c46f7c2abd","repo":"jdx/mise","slug":"context-malformed-sha256","errorCode":null,"errorMessage":"#{context}: malformed sha256","messagePattern":"#(.+?): malformed sha256","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/shim.rb","lineNumber":74,"sourceCode":"  $stderr.puts \"Error: #{message}\"\n  exit 1\nend\n\nclass ShimUnsupportedError < StandardError; end\n\ndef shim_unsupported!(feature)\n  raise ShimUnsupportedError,\n        \"formula uses `#{feature}`, which mise's source-build shim does not support\"\nend\n\nmodule MiseDownload\n  module_function\n\n  # download with redirects into the cache, verify, return the path\n  def fetch(url, sha256, context)\n    raise \"#{context}: missing sha256\" if sha256.to_s.strip.empty?\n    sha256 = sha256.to_s.strip.downcase\n    raise \"#{context}: malformed sha256\" unless sha256.match?(/\\A[0-9a-f]{64}\\z/)\n\n    MISE_BREW_CACHE.mkpath\n    dest = MISE_BREW_CACHE + \"#{sha256}--#{File.basename(URI(url).path)}\"\n    unless dest.file? && Digest::SHA256.file(dest).hexdigest == sha256\n      ohai \"Downloading #{url}\"\n      tmp = Pathname.new(\"#{dest}.incomplete\")\n      URI.open(url, \"rb\", redirect: true) do |remote|\n        tmp.open(\"wb\") { |f| IO.copy_stream(remote, f) }\n      end\n      actual = Digest::SHA256.file(tmp).hexdigest\n      if actual != sha256\n        tmp.unlink\n        raise \"#{context}: sha256 mismatch (expected #{sha256}, got #{actual})\"\n      end\n      tmp.rename(dest)\n    end\n    dest\n  end","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/shim.rb#L56-L92","documentation":"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.","triggerScenarios":"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).","commonSituations":"Copy-paste errors from terminal output (wrong hash algorithm column), digests from `md5sum` instead of `shasum -a 256`, formulas with corrupted checksum fields.","solutions":["Recompute the digest with `shasum -a 256` (SHA-256, 64 hex chars) and correct the package definition","Remove any prefixes/suffixes/quotes around the digest","Ensure the value is a plain string of 64 hex characters","If the artifact changed upstream, re-pin a new legitimate digest"],"exampleFix":"# before\nsha256 = \"d41d8cd98f00b204e9800998ecf8427e\"  # md5\n# after\nsha256 = \"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad\"","handlingStrategy":"validation","validationCode":"unless sha256.to_s.match?(/\\A[0-9a-fA-F]{64}\\z/)\n  raise \"#{context}: sha256 must be 64 hex chars\"\nend","typeGuard":"def sha256?(s) = s.to_s.match?(/\\A[0-9a-f]{64}\\z/)","tryCatchPattern":"begin\n  MiseDownload.fetch(url, sha256, context)\nrescue RuntimeError => e\n  abort \"bad checksum for #{context}: #{e.message}\"\nend","preventionTips":["Verify digest algorithm before pasting (SHA-256 is 64 hex chars)","Strip surrounding whitespace/quotes from copied digests","Lint package files for checksum format in CI"],"tags":["ruby","checksum","validation","brew-shim"],"backgroundTag":"invalid-argument-format","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}