jdx/mise · error
Cargo workspace member pattern
Error message
Cargo workspace member pattern {member:?} must be relative What it means
mise's Cargo workspace task provider globs workspace member patterns from Cargo.toml to discover member crates. Member patterns are joined onto the workspace root as `<root>/<member>` and globbed, so they must be relative paths or globs. When a member entry is an absolute path (e.g. `/foo` or `C:\foo`), the provider bails with this error because an absolute member would produce a broken or unintended glob pattern.
Solutions
- Change the members entry in Cargo.toml to a path relative to the workspace root (e.g. `"crates/util"` or `"crates/*"`).
- If the member genuinely lives outside the workspace root, move it under the root or restructure; Cargo itself also forbids absolute member patterns relative resolution outside the root.
- Verify with `cargo metadata` that Cargo accepts the workspace before running mise tasks.
Example fix
# before (Cargo.toml) [workspace] members = ["/home/user/proj/crates/util"] # after [workspace] members = ["crates/util"]
Defensive patterns
Strategy: validation
Validate before calling
fn validate_members(members: &[String]) -> Result<(), String> {
for m in members {
if Path::new(m).is_absolute() {
return Err(format!("member {m:?} must be relative to workspace root"));
}
}
Ok(())
} Type guard
fn is_relative_member(m: &str) -> bool { !Path::new(m).is_absolute() } Prevention
- Always write members as paths relative to the workspace root in Cargo.toml
- Let `cargo new` / generators place members under the root and use globs like "crates/*"
- CI-lint Cargo.toml to reject absolute member entries
When it happens
Trigger: Running a task that triggers workspace discovery when a `Cargo.toml` `[workspace] members = [...]` (or `default-members`) entry is an absolute path like `members = ["/opt/crates/util"]` instead of a relative path or glob.
Common situations: Hand-edited Cargo.toml where someone pasted an absolute path; tools or scripts generating members entries from absolute paths; cross-platform configs where Windows drive-letter paths sneak in.
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
- [bootstrap].config_roots did not match any config roots
- failed to discover workspace providers
- [monorepo].config_roots did not match any config roots
- removed workspace project
- uv workspace member pattern
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/59b15a7461a54cc2.
Report an issue: GitHub.
Appendix: source
Thrown at src/task/workspace/cargo.rs:254
fn discover_members(
pattern_root: &Path,
canonical_root: &Path,
members: &[String],
excludes: &[Pattern],
context: &WorkspaceDiscoveryContext,
) -> Result<BTreeSet<PathBuf>> {
let options = MatchOptions {
case_sensitive: true,
require_literal_separator: true,
require_literal_leading_dot: true,
};
// Use the caller's non-canonical path for globbing. Windows canonical paths
// use a verbatim `\\?\` prefix whose `?` is interpreted as a glob token.
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!("Cargo 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 Cargo workspace member pattern {member:?}"))?
{
let candidate = candidate.wrap_err_with(|| {
format!("failed to evaluate Cargo workspace member pattern {member:?}")
})?;
if !context.is_file(&candidate.join(CARGO_TOML)) {
continue;
}
let candidate = context.canonicalize(&candidate).wrap_err_with(|| {
format!(
"failed to resolve Cargo workspace member {}",
candidate.display()
)
})?;
let relative = relative_root(canonical_root, &candidate)?;View on GitHub (pinned to 533346cc37)