jdx/mise · error

Python locks support registry wheels only

Error message

Python locks support registry wheels only

What it means

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.

Solutions

  1. Regenerate the lock with a setup where all resolved dependencies come from PyPI: `mise lock --bump <tool>`.
  2. Remove or replace git/path-based dependencies with registry-published equivalents in the tool's dependency set.
  3. If you hand-crafted the lock, re-emit sources as `{ registry = ... }` entries or better, let mise/uv regenerate it.
  4. Check uv configuration for index/path overrides that introduce non-registry sources.

Example fix

// before (in uv.lock, non-registry source)
[package.source]
git = "https://github.com/org/repo"

// after (registry source)
[package.source]
registry = "https://pypi.org/simple"
Defensive patterns

Strategy: validation

Validate before calling

// ensure dependencies resolve from PyPI only before locking
grep -r 'git\|path\|editable' mise.lock && echo 'non-registry source found';

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/5206cae4d3537e12. Report an issue: GitHub.

Appendix: source

Thrown at src/backend/pipx/lock.rs:395

                    .and_then(toml::Value::as_array)
                    .into_iter()
                    .flatten()
                    .filter_map(toml::Value::as_str)
                    .map(|extra| Self::normalize_package_name(extra.trim()))
                    .collect::<std::collections::BTreeSet<_>>();
                if requirements.len() != expected.len()
                    || root_requirement.is_none()
                    || extras != locked_extras
                {
                    bail!(
                        "uv graph root requirements do not match the requested package and extras"
                    );
                }
                virtual_root = true;
                continue;
            }
            if source.len() != 1 || !source.contains_key("registry") {
                bail!("Python locks support registry wheels only");
            }
            if name == Self::normalize_package_name(&self.tool_name())
                && 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:"));

View on GitHub (pinned to 533346cc37)