jdx/mise · error
uv workspace member pattern
Error message
uv workspace member pattern {member:?} must be relative What it means
uv workspace tool.uv.workspace.members entries are glob patterns that mise expands relative to the workspace root. Absolute paths cannot be joined into the escaped-root glob pattern, so mise rejects them up front rather than producing a broken pattern. uv itself also documents members as root-relative globs.
Solutions
- Change the member entry to a path relative to the workspace root, e.g. "packages/*".
- If the package lives outside the workspace directory, move it inside or use a symlink within the root.
- Use glob patterns like "members/*" or "." for the root project itself.
Example fix
# before [tool.uv.workspace] members = ["/home/me/proj/packages/*"] # after [tool.uv.workspace] members = ["packages/*"]
Defensive patterns
Strategy: validation
Validate before calling
const members = doc['tool']?.['uv']?.['workspace']?.['members'] ?? [];
for (const m of members) {
if (require('path').isAbsolute(m)) throw new Error(`member ${m} must be relative`);
} Prevention
- Always express uv workspace members relative to the workspace root.
- Use globs (packages/*) instead of enumerating absolute paths.
When it happens
Trigger: discover_members processes a members array entry like "/abs/path/pkg" or "C:\\pkg" where Path::is_absolute() is true.
Common situations: Copy-pasting an absolute path from `pwd` output into pyproject.toml; IDE auto-complete inserting full paths; generated configs from scripts that emitted absolute paths.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- uv project at has an empty project.name
- uv workspace member at
- Cargo workspace member pattern
- exposes no executable scripts
- invalid Python entry point name
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/b53aba6d9694a287.
Report an issue: GitHub.
Appendix: 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 533346cc37)