jdx/mise · error
brew-cask: : cask metadata has no sha256
Error message
brew-cask:{}: cask metadata has no sha256 What it means
Every downloaded cask archive must be verified against a sha256 checksum. `fetch_archive` accepts the special value "no_check" (explicit opt-out), a real digest (verified via hash::ensure_checksum), or — if the cask JSON has no sha256 field at all — throws this error. A missing digest means the cask metadata is incomplete and the download cannot be proven intact, so the fetch refuses to proceed.
Solutions
- Add a sha256 digest to the cask's url stanza in the tap (sha256 of the downloaded artifact)
- Set sha256 to "no_check" explicitly if verification is intentionally skipped
- Re-fetch cask metadata in case the JSON was truncated or parsed incorrectly
Example fix
// before (cask url stanza) url "https://example.com/foo.zip" // after url "https://example.com/foo.zip" sha256 "9a1f...c3"
Defensive patterns
Strategy: validation
Validate before calling
// Check cask metadata for a checksum before downloading
match cask.sha256.as_deref() {
Some("no_check") => {},
Some(sha) if sha.len() == 64 && sha.chars().all(|c| c.is_ascii_hexdigit()) => {},
_ => eprintln!("cask metadata must include a sha256 (or explicit \"no_check\")"),
} Prevention
- Always include sha256 in cask url stanzas
- Use "no_check" explicitly rather than omitting the field when skipping verification
- Re-sync cask metadata if fetched JSON appears truncated
When it happens
Trigger: fetch_archive (from fetch_and_stage or prewarm_downloads) processes a Cask whose `sha256` field is None — the API/tap JSON omitted the sha256 key for the archive stanza.
Common situations: A tap publishes a cask without a sha256 in its url stanza; a parsing bug or schema change drops the sha256 field from the fetched JSON; a hand-written cask JSON missing the checksum.
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
- : API metadata has no formula checksum
- app target is outside an allowed Applications directory
- artifact target has changed
- binary target is not an owned Caskroom symlink
- brew-cask: : git only_path must name a directory within the…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/e21204af92282436.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/fetch.rs:254
let url_hash = &hash::hash_sha256_to_str(&cask.url)[..12];
let archive = cache_dir.join(format!(
"{}-{}-{url_hash}-{filename}",
cask.token, cask.version
));
if !archive.exists() {
HTTP.download_file(&cask.url, &archive, pr).await?;
// Strip macOS quarantine so it doesn't propagate into extracted/copied artifacts.
let _ = std::process::Command::new("xattr")
.args(["-d", "com.apple.quarantine"])
.arg(&archive)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status();
}
match cask.sha256.as_deref() {
Some("no_check") => {}
Some(sha256) => hash::ensure_checksum(&archive, sha256, pr, "sha256")?,
None => bail!("brew-cask:{}: cask metadata has no sha256", cask.token),
}
Ok(archive)
}
pub(super) fn extract_archive(
cask: &Cask,
archive: &Path,
pr: Option<&dyn SingleReport>,
) -> Result<PathBuf> {
let extract_dir = crate::dirs::CACHE
.join("system-brew")
.join("cask-extract")
.join(format!("{}-{}", cask.token, cask.version));
file::remove_all(&extract_dir)?;
file::create_dir_all(&extract_dir)?;
let filename = archive
.file_name()
.and_then(|f| f.to_str())View on GitHub (pinned to 533346cc37)