{"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/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/shim.rb#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Recompute the digest with sha256sum and paste the full 64-hex-character value.","Strip any 'sha256:'/'SHA256=' prefix and convert uppercase hex to lowercase.","Verify the field isn't an md5/sha1 value (32/40 chars) — replace it with an actual sha256."],"exampleFix":"// before\nsha256 = \"ABCDEF1234567890\"\n// after\nsha256 = \"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\"","handlingStrategy":"validation","validationCode":"# ruby format check before calling fetch\nsha256 = sha256.to_s.strip.downcase\nraise \"bad sha256 format\" unless sha256.match?(/\\A[0-9a-f]{64}\\z/)","typeGuard":null,"tryCatchPattern":"begin\n  MiseDownload.fetch(url, sha256, context)\nrescue RuntimeError => e\n  raise unless e.message.include?(\"malformed sha256\")\n  # recompute and retry with a corrected digest\nend","preventionTips":["Paste full 64-char digests; verify length with wc before committing.","Never reuse md5/sha1 values in sha256 fields.","Strip algorithm-name prefixes when copying from tool output."],"tags":["ruby","download","checksum","validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}