{"record":{"id":"78271635dcd44f09","repo":"jdx/mise","slug":"name-has-a-wheel-without-a-sha256-hash","errorCode":null,"errorMessage":"{name} has a wheel without a SHA256 hash","messagePattern":"(.+?) has a wheel without a SHA256 hash","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/pipx/lock.rs","lineNumber":416,"sourceCode":"                && package.get(\"version\").and_then(toml::Value::as_str) == Some(&tv.version)\n            {\n                root = true;\n            }\n            let wheels = package\n                .get(\"wheels\")\n                .and_then(toml::Value::as_array)\n                .filter(|v| !v.is_empty())\n                .ok_or_else(|| {\n                    eyre!(\"{name} has no published wheels; Python graph locks require wheels\")\n                })?;\n            for wheel in wheels {\n                let hash = wheel\n                    .get(\"hash\")\n                    .and_then(toml::Value::as_str)\n                    .and_then(|h| h.strip_prefix(\"sha256:\"));\n                if !hash.is_some_and(|h| h.len() == 64 && h.bytes().all(|c| c.is_ascii_hexdigit()))\n                {\n                    bail!(\"{name} has a wheel without a SHA256 hash\");\n                }\n            }\n        }\n        if !root || !virtual_root {\n            bail!(\"Python lock is missing the requested root package\");\n        }\n        validate_portable_urls(&toml::Value::Table(lock.graph.clone()))?;\n        // No arbitrary project settings or build systems are accepted from a lockfile.\n        if lock.project.len() != 1 || project.len() != 4 {\n            bail!(\"unsupported Python lock project settings\");\n        }\n        Ok(())\n    }\n\n    pub(super) async fn install_uv_lock(\n        &self,\n        ctx: &InstallContext,\n        tv: &ToolVersion,","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/pipx/lock.rs#L398-L434","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n[[package.wheels]]\nurl = \"https://files.pythonhosted.org/.../pkg-1.0-py3-none-any.whl\"\n\n// after\n[[package.wheels]]\nurl = \"https://files.pythonhosted.org/.../pkg-1.0-py3-none-any.whl\"\nhash = \"sha256:0123abcd...\"  # 64 hex chars","handlingStrategy":"validation","validationCode":"// verify every wheel hash before trusting a lock\nfor w in lock.wheels: assert re.fullmatch(r'[0-9a-f]{64}', w.hash.removeprefix('sha256:'));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["python","uv","lockfile","checksum"],"backgroundTag":"checksum-mismatch","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"}