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
- Change the member entry to a path relative to the workspace root, e.g. "packages/*"
- If you need to reference an external directory, use a relative path like "../shared-lib" instead of an absolute one
- 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
- Always express workspace members relative to the workspace root
- Avoid IDE auto-completion inserting absolute paths
- Use globs like packages/* rather than enumerated absolute dirs
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
- uv project at {} has an empty project.name
- uv workspace member at {} is missing {PYPROJECT_TOML}
- [monorepo].config_roots did not match any config roots
- task {} cache outputs require at least one non-excluded patt
- output pattern {output:?} matched no files
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/b53aba6d9694a287.
Report an issue: GitHub.