{"record":{"id":"5206cae4d3537e12","repo":"jdx/mise","slug":"python-locks-support-registry-wheels-only","errorCode":null,"errorMessage":"Python locks support registry wheels only","messagePattern":"Python locks support registry wheels only","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/pipx/lock.rs","lineNumber":395,"sourceCode":"                    .and_then(toml::Value::as_array)\n                    .into_iter()\n                    .flatten()\n                    .filter_map(toml::Value::as_str)\n                    .map(|extra| Self::normalize_package_name(extra.trim()))\n                    .collect::<std::collections::BTreeSet<_>>();\n                if requirements.len() != expected.len()\n                    || root_requirement.is_none()\n                    || extras != locked_extras\n                {\n                    bail!(\n                        \"uv graph root requirements do not match the requested package and extras\"\n                    );\n                }\n                virtual_root = true;\n                continue;\n            }\n            if source.len() != 1 || !source.contains_key(\"registry\") {\n                bail!(\"Python locks support registry wheels only\");\n            }\n            if name == Self::normalize_package_name(&self.tool_name())\n                && 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:\"));","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/pipx/lock.rs#L377-L413","documentation":"mise only replays uv locks whose wheels come from a package registry; each lock entry's source table must contain exactly one key and it must be `registry`. Source entries like git, path, directory, or editable installs would make the lock non-portable and non-reproducible, so validation fails.","triggerScenarios":"Thrown from validate_uv_lock when any package in the lock graph has a source table that is not exactly one `registry` entry — e.g. a git or local-path dependency was resolved into the graph, or the lock file was hand-edited or produced by an unusual uv configuration.","commonSituations":"The underlying project (or a dependency) pulls a package from a git URL or local path; someone crafted a lock outside mise's normal `mise lock` flow; an editable/local dev install leaked into the lock; uv resolved a dependency that only exists outside PyPI.","solutions":["Regenerate the lock with a setup where all resolved dependencies come from PyPI: `mise lock --bump <tool>`.","Remove or replace git/path-based dependencies with registry-published equivalents in the tool's dependency set.","If you hand-crafted the lock, re-emit sources as `{ registry = ... }` entries or better, let mise/uv regenerate it.","Check uv configuration for index/path overrides that introduce non-registry sources."],"exampleFix":"// before (in uv.lock, non-registry source)\n[package.source]\ngit = \"https://github.com/org/repo\"\n\n// after (registry source)\n[package.source]\nregistry = \"https://pypi.org/simple\"","handlingStrategy":"validation","validationCode":"// ensure dependencies resolve from PyPI only before locking\ngrep -r 'git\\|path\\|editable' mise.lock && echo 'non-registry source found';","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid tools whose dependency tree pulls git/path packages","Prefer registry-published dependency versions","Re-lock via mise rather than importing a project's own uv.lock"],"tags":["python","uv","lockfile","registry-only"],"backgroundTag":"unsupported-config-value","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"}