jdx/mise · error

workspace provider {:?} attributed lockfile {:?} to foreign

Error message

workspace provider {:?} attributed lockfile {:?} to foreign project {id:?}

What it means

When WorkspaceProjectGraph::affected_projects_for_lockfile() asks each WorkspaceProvider to attribute a changed lockfile, every returned ProjectId must live in that provider's own namespace: it must start with "{provider.id()}:". This error means a provider returned an ID carrying a different (foreign) prefix, which would let one provider's attribution mutate another provider's projects.

Source

Thrown at src/task/workspace.rs:964

        lockfile_path: &Path,
        before: Option<&str>,
        after: Option<&str>,
    ) -> Result<Option<BTreeSet<ProjectId>>> {
        let mut providers = providers.to_vec();
        providers.sort_by(|left, right| left.id().cmp(right.id()));
        let mut recognized = false;
        let mut affected = BTreeSet::new();
        for provider in providers {
            let Some(projects) =
                provider.affected_projects_for_lockfile(lockfile_path, before, after, self)?
            else {
                continue;
            };
            recognized = true;
            let expected_prefix = format!("{}:", provider.id());
            for id in projects {
                if !id.as_str().starts_with(&expected_prefix) {
                    bail!(
                        "workspace provider {:?} attributed lockfile {:?} to foreign project {id:?}",
                        provider.id(),
                        lockfile_path
                    );
                }
                if !self.projects.contains_key(&id) {
                    bail!(
                        "workspace provider {:?} attributed lockfile {:?} to unknown project {id:?}",
                        provider.id(),
                        lockfile_path
                    );
                }
                affected.insert(id);
            }
        }
        Ok(recognized.then_some(affected))
    }

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Construct every returned ID with ProjectId::new(self.id(), local_id) so the prefix can never drift
  2. If the provider changes or the code was adapted, re-run attribution and assert id.as_str().starts_with(&format!("{}:", self.id())) in tests
  3. Return None (lockfile not recognized) instead of attributing to projects owned by other providers

Example fix

// before (custom provider)
fn affected_projects_for_lockfile(...) -> Result<Option<BTreeSet<ProjectId>>> {
    Ok(Some(BTreeSet::from(["cargo:app".parse()?]))) // foreign namespace
}

// after
fn affected_projects_for_lockfile(...) -> Result<Option<BTreeSet<ProjectId>>> {
    Ok(Some(BTreeSet::from([ProjectId::new(self.id(), "app")?])))
}
Defensive patterns

Strategy: validation

Validate before calling

let prefix = format!("{}:", self.id());
let ids: BTreeSet<ProjectId> = candidates
    .into_iter()
    .filter(|id| id.as_str().starts_with(&prefix))
    .collect();
Ok(Some(ids))

Type guard

fn in_own_namespace(provider_id: &str, id: &ProjectId) -> bool {
    id.as_str().starts_with(&format!("{provider_id}:"))
}

Prevention

When it happens

Trigger: Implementing a custom WorkspaceProvider whose affected_projects_for_lockfile returns IDs like "cargo:some-crate" while provider.id() returns e.g. "myprov"; hand-formatting IDs (format!("{}:{}", wrong_ns, local)) instead of constructing them with ProjectId::new(self.id(), local); copy-pasting another provider's attribution logic without changing the namespace.

Common situations: Writing a first-party workspace provider for an in-house build system; adapting the node.rs provider sample; provider id() renamed but attribution code still returns IDs under the old namespace.

Related errors


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