jdx/mise · error

unknown workspace project {id:?}

Error message

unknown workspace project {id:?}

What it means

WorkspaceProjectGraph::affected_projects() computes the set of changed projects plus every project that transitively depends on them. It fails fast when any passed ProjectId is not a key in the graph's project map. Project IDs are provider-namespaced strings (e.g. "cargo:my-crate", "go:example.com/mod") minted during discovery from Cargo.toml, go.work, package.json, or pyproject.toml, so any ID that was not discovered in the current run is rejected.

Source

Thrown at src/task/workspace.rs:819

    pub fn affected_projects<'a>(
        &self,
        changed: impl IntoIterator<Item = &'a ProjectId>,
    ) -> Result<BTreeSet<ProjectId>> {
        let mut dependents = BTreeMap::<ProjectId, BTreeSet<ProjectId>>::new();
        for project in self.projects() {
            for dependency in &project.dependencies {
                dependents
                    .entry(dependency.clone())
                    .or_default()
                    .insert(project.id.clone());
            }
        }

        let mut affected = BTreeSet::new();
        let mut pending = Vec::new();
        for id in changed {
            if !self.projects.contains_key(id) {
                bail!("unknown workspace project {id:?}");
            }
            if affected.insert(id.clone()) {
                pending.push(id.clone());
            }
        }

        while let Some(id) = pending.pop() {
            for dependent in dependents.get(&id).into_iter().flatten() {
                if affected.insert(dependent.clone()) {
                    pending.push(dependent.clone());
                }
            }
        }
        Ok(affected)
    }

    /// Maps changed paths to affected projects, including workspace-global inputs.
    ///

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Verify the ID exists first with graph.get(&id) and log/skip unknown IDs instead of failing
  2. Re-derive the ID list from the current graph (graph.projects()) rather than reusing IDs captured in a previous session or cache
  3. Check [monorepo.projects] overrides in mise.toml for a remove = true entry on that ID
  4. Confirm the owning provider actually discovered the project (member listed in Cargo.toml [workspace].members / go.work use / pnpm workspace globs, not excluded)

Example fix

// before
let affected = graph.affected_projects(["cargo:renamed_crate".parse()?])?;

// after
let id = "cargo:renamed_crate".parse()?;
if graph.get(&id).is_none() {
    warn!("project {id} no longer in workspace graph; skipping");
    return Ok(Default::default());
}
let affected = graph.affected_projects([id])?;
Defensive patterns

Strategy: validation

Validate before calling

let known: Vec<&ProjectId> = requested_ids.iter().filter(|id| graph.get(id).is_some()).collect();
for id in requested_ids.iter().filter(|id| graph.get(id).is_none()) {
    warn!("skipping unknown workspace project {id}");
}
let affected = graph.affected_projects(known.iter().copied())?;

Type guard

fn is_known_project(graph: &WorkspaceProjectGraph, raw: &str) -> bool {
    matches!(raw.parse::<ProjectId>(), Ok(id) if graph.get(&id).is_some())
}

Try / catch

match graph.affected_projects(ids) {
    Ok(set) => set,
    Err(err) if err.to_string().contains("unknown workspace project") => {
        warn!("stale project reference: {err}");
        Default::default()
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Calling graph.affected_projects(ids) with an ID that is not in self.projects: an ID string that was cached or saved from an earlier run (crate/module renamed since), an ID whose project was removed via a [monorepo.projects."<id>"] remove = true override, an ID from a provider that failed lenient discovery (provider_errors retained), or a hand-typed ID with a wrong provider prefix or local part.

Common situations: Stale cached project IDs after renaming a Cargo crate or Go module path; referencing a project that a colleague removed from workspace members; monorepo config drift between branches; a typo like "cargo:my-crate " (whitespace) or "my-crate" (missing provider prefix).

Related errors


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