jdx/mise · error

uv workspace member pattern {member:?} must be relative

Error message

uv workspace member pattern {member:?} must be relative

What it means

uv workspace `members` patterns are globbed relative to the workspace root; an absolute path pattern would produce a broken `escaped_root/member` glob and is rejected outright. The check runs before glob expansion in discover_members.

Source

Thrown at src/task/workspace/uv.rs:294

        })
        .collect()
}

fn discover_members(
    pattern_root: &Path,
    canonical_root: &Path,
    members: &[String],
    excludes: &[Pattern],
    context: &WorkspaceDiscoveryContext,
) -> Result<BTreeSet<PathBuf>> {
    let options = match_options();
    // Avoid canonical Windows roots here because their verbatim `\\?\` prefix
    // contains a character that glob interprets as a wildcard.
    let escaped_root = Pattern::escape(&pattern_root.to_string_lossy());
    let mut roots = BTreeSet::new();
    for member in members {
        if Path::new(member).is_absolute() {
            bail!("uv workspace member pattern {member:?} must be relative");
        }
        let pattern = format!("{escaped_root}/{member}");
        for candidate in glob::glob_with(&pattern, options)
            .wrap_err_with(|| format!("invalid uv workspace member pattern {member:?}"))?
        {
            let candidate = candidate.wrap_err_with(|| {
                format!("failed to evaluate uv workspace member pattern {member:?}")
            })?;
            if !context.is_dir(&candidate) {
                continue;
            }
            let candidate = context.canonicalize(&candidate).wrap_err_with(|| {
                format!(
                    "failed to resolve uv workspace member {}",
                    candidate.display()
                )
            })?;
            let relative = relative_root(canonical_root, &candidate)?;

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Change the member entry to a path relative to the workspace root, e.g. "packages/*"
  2. If you need to reference an external directory, use a relative path like "../shared-lib" instead of an absolute one
  3. Fix Windows entries to use forward-slash relative paths rather than drive-letter absolute paths

Example fix

# before
[tool.uv.workspace]
members = ["/home/me/proj/packages/api"]

# after
[tool.uv.workspace]
members = ["packages/api"]
Defensive patterns

Strategy: validation

Validate before calling

# ensure all uv workspace member patterns are relative
import tomllib
m = tomllib.load(open('pyproject.toml','rb'))
for pat in m.get('tool', {}).get('uv', {}).get('workspace', {}).get('members', []):
    if not pat.startswith(('..', './')) and '/' in pat and pat[0] in '/~':
        raise SystemExit(f'member pattern {pat!r} must be relative')

Prevention

When it happens

Trigger: A pyproject.toml `[tool.uv.workspace] members = ["/abs/path/pkg"]` (or a Windows drive letter / verbatim `\\?\` path) is expanded by discover_with_context; discover_members bails because Path::is_absolute() is true.

Common situations: IDE- or tool-generated member entries that were absolute; copying member lists between machines; Windows users pasting `C:\...`-style paths into members.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/b53aba6d9694a287. Report an issue: GitHub.