jdx/mise · error

workspace project {:?} depends on unknown project {:?}

Error message

workspace project {:?} depends on unknown project {:?}

What it means

After provider discovery and [monorepo.projects] overrides are applied, WorkspaceProjectGraph::validate() checks every dependency edge: each ID in a project's dependencies must itself be a project in the graph. A dangling edge — a project depending on an ID that was never discovered — aborts graph construction.

Source

Thrown at src/task/workspace.rs:1046

            if !visited.insert(dependency_id.clone()) {
                continue;
            }
            self.collect_matching_dependencies(dependency_id, visited, matches, matching);
            let dependency = self
                .projects
                .get(dependency_id)
                .expect("workspace project graph is validated");
            if matches(dependency) {
                matching.push(dependency);
            }
        }
    }

    fn validate(&self) -> Result<()> {
        for project in self.projects() {
            for dependency in &project.dependencies {
                if self.get(dependency).is_none() {
                    bail!(
                        "workspace project {:?} depends on unknown project {:?}",
                        project.id,
                        dependency
                    );
                }
            }
        }
        if let Some(path) = self.find_cycle() {
            return Err(WorkspaceProjectCycleError { path }.into());
        }
        Ok(())
    }

    fn find_cycle(&self) -> Option<Vec<ProjectId>> {
        let mut visited = BTreeSet::new();
        let mut active = BTreeMap::new();
        let mut path = Vec::new();
        for id in self.projects.keys() {

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Fix the dependency ID: include the provider prefix and exact local ID ("cargo:shared", "go:example.com/shared")
  2. Make the target discoverable: list it in [workspace] members / go.work use / workspace globs, or remove it from exclude
  3. Drop the edge with depends_remove instead of depending on a nonexistent project
  4. If the project should exist outside providers, add it via an override with root = "path" so it enters the graph before validation

Example fix

# before (mise.toml)
[monorepo.projects."cargo:app"]
depends_add = ["shared"]

# after
[monorepo.projects."cargo:app"]
depends_add = ["cargo:shared"]
# and ensure Cargo.toml [workspace] members/exclude actually include crates/shared
Defensive patterns

Strategy: validation

Validate before calling

// before calling discover_all_with_overrides
for (raw_id, cfg) in &overrides {
    let id = raw_id.parse::<ProjectId>()?;
    for dep in cfg.depends.as_ref().into_iter().flatten().chain(&cfg.depends_add) {
        let dep = dep.parse::<ProjectId>()?;
        if graph.get(&dep).is_none() && !overrides.contains_key(dep.as_str()) {
            warn!("override for {id} references unknown dependency {dep}");
        }
    }
}

Type guard

fn override_edges_are_resolvable(graph: &WorkspaceProjectGraph, overrides: &BTreeMap<String, WorkspaceProjectOverride>) -> Vec<String> {
    let mut problems = Vec::new();
    for (raw, cfg) in overrides {
        for dep in cfg.depends.as_ref().into_iter().flatten().chain(&cfg.depends_add) {
            let ok = dep.parse::<ProjectId>().map(|d| graph.get(&d).is_some() || overrides.contains_key(d.as_str())).unwrap_or(false);
            if !ok { problems.push(format!("{raw} -> {dep}")); }
        }
    }
    problems
}

Try / catch

if let Err(err) = WorkspaceProjectGraph::discover_all_with_overrides(&providers, root, &overrides) {
    if err.to_string().contains("depends on unknown project") {
        return user_facing_config_error(err, "check [monorepo.projects] depends/depends_add entries");
    }
    return Err(err);
}

Prevention

When it happens

Trigger: An override like [monorepo.projects."cargo:app".depends_add] naming an ID that does not exist (typo, missing provider prefix, or target not discovered); provider-inferred edges to excluded members (a Cargo workspace.dependencies path dependency whose crate is in exclude, a go.work module dependency on a module outside the use list); removing a project with remove = true while other projects still depend on it is handled by edge-stripping, but a depends entry pointing at an explicitly removed project re-added via depends_add is not.

Common situations: Writing depends_add = ["shared"] and forgetting the "cargo:" prefix; pointing at a crate that Cargo.toml excludes; a package.json/glob filter that drops a member other members import; edges surviving from a renamed project.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/2c95455693b23ee3. Report an issue: GitHub.