jdx/mise · error

uv workspace member at {} is missing {PYPROJECT_TOML}

Error message

uv workspace member at {} is missing {PYPROJECT_TOML}

What it means

After glob expansion, each candidate directory that matches a uv workspace member pattern must contain a pyproject.toml (PYPROJECT_TOML) to be a valid member. When a matched candidate lacks that file, discover_members treats the workspace definition as inconsistent and errors naming the missing file.

Source

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

        {
            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)?;
            if is_excluded(&relative, excludes) {
                continue;
            }
            if !context.is_file(&candidate.join(PYPROJECT_TOML)) {
                bail!(
                    "uv workspace member at {} is missing {PYPROJECT_TOML}",
                    relative.display()
                );
            }
            roots.insert(candidate);
        }
    }
    Ok(roots)
}

fn match_options() -> MatchOptions {
    MatchOptions {
        case_sensitive: true,
        require_literal_separator: true,
        require_literal_leading_dot: true,
    }
}

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Add a pyproject.toml to the reported member directory if it is a real workspace member
  2. Narrow the members glob (e.g. packages/api instead of packages/*) so non-member directories don't match
  3. Add the non-member directory to [tool.uv.workspace] exclude

Example fix

# before
[tool.uv.workspace]
members = ["packages/*"]

# after
[tool.uv.workspace]
members = ["packages/*"]
exclude = ["packages/scratch"]
Defensive patterns

Strategy: validation

Validate before calling

# every directory matched by member globs must contain pyproject.toml
import glob, os
for d in glob.glob('packages/*'):
    if os.path.isdir(d) and not os.path.exists(os.path.join(d, 'pyproject.toml')):
        print(f'{d} matches members glob but lacks pyproject.toml — exclude it')

Prevention

When it happens

Trigger: A glob pattern like `packages/*` in [tool.uv.workspace].members matches a directory (e.g. packages/README-only or a build-output dir) that has no pyproject.toml, and it is not excluded via the `exclude` list.

Common situations: Broad wildcard members catching scratch/output directories; a member directory emptied or renamed so its pyproject.toml is gone; an exclude entry typo'd so the directory is no longer skipped.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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