jdx/mise · error
has a wheel without a SHA256 hash
Error message
{name} has a wheel without a SHA256 hash What it means
Every wheel recorded in the uv lock must carry a verifiable SHA256 integrity hash. validate_uv_lock extracts each wheel's `hash`, strips the `sha256:` prefix, and requires a 64-character hex digest; anything else (missing hash, wrong prefix, wrong length or non-hex characters) is rejected so installs cannot pull tampered or unverifiable artifacts.
Solutions
- Regenerate the lock with hashes: `mise lock --bump <tool>` using a current uv (>= 0.12.10).
- If hand-editing, ensure each wheel has `hash = "sha256:<64-hex>"` matching the artifact digest.
- Point uv at an index that serves per-file hashes (e.g. official PyPI) and re-lock.
- Check for tooling (formatting, filtering scripts) that stripped the hash fields from the lock.
Example fix
// before [[package.wheels]] url = "https://files.pythonhosted.org/.../pkg-1.0-py3-none-any.whl" // after [[package.wheels]] url = "https://files.pythonhosted.org/.../pkg-1.0-py3-none-any.whl" hash = "sha256:0123abcd..." # 64 hex chars
Defensive patterns
Strategy: validation
Validate before calling
// verify every wheel hash before trusting a lock
for w in lock.wheels: assert re.fullmatch(r'[0-9a-f]{64}', w.hash.removeprefix('sha256:')); Prevention
- Always generate locks with a uv version that records hashes
- Never run scripts that strip or rewrite mise.lock fields
- Use indexes that serve per-file hashes
When it happens
Trigger: Thrown from validate_uv_lock when a wheel entry in the lock graph has no `hash` key, a hash lacking the `sha256:` prefix, or a malformed digest (not 64 ASCII hex characters). Calls come from prepare_install_version, resolve_uv_lock, install_uv_lock.
Common situations: A hand-edited or truncated mise.lock; a lock generated with hash checking disabled or by tooling that strips hashes; a private index that omits hashes; an old uv version that emitted different hash formats.
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
- Python dependency graphs require lockfile revision 2; run…
- Python lock does not match the requested tool; run `mise…
- Python lock is missing the requested root package
- Python locks support registry wheels only
- unsupported Python lock project settings
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/78271635dcd44f09.
Report an issue: GitHub.
Appendix: source
Thrown at src/backend/pipx/lock.rs:416
&& package.get("version").and_then(toml::Value::as_str) == Some(&tv.version)
{
root = true;
}
let wheels = package
.get("wheels")
.and_then(toml::Value::as_array)
.filter(|v| !v.is_empty())
.ok_or_else(|| {
eyre!("{name} has no published wheels; Python graph locks require wheels")
})?;
for wheel in wheels {
let hash = wheel
.get("hash")
.and_then(toml::Value::as_str)
.and_then(|h| h.strip_prefix("sha256:"));
if !hash.is_some_and(|h| h.len() == 64 && h.bytes().all(|c| c.is_ascii_hexdigit()))
{
bail!("{name} has a wheel without a SHA256 hash");
}
}
}
if !root || !virtual_root {
bail!("Python lock is missing the requested root package");
}
validate_portable_urls(&toml::Value::Table(lock.graph.clone()))?;
// No arbitrary project settings or build systems are accepted from a lockfile.
if lock.project.len() != 1 || project.len() != 4 {
bail!("unsupported Python lock project settings");
}
Ok(())
}
pub(super) async fn install_uv_lock(
&self,
ctx: &InstallContext,
tv: &ToolVersion,View on GitHub (pinned to 533346cc37)