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

  1. Change the members entry in Cargo.toml to a path relative to the workspace root (e.g. `"crates/util"` or `"crates/*"`).
  2. 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.
  3. 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

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


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)