jdx/mise · error
workspace provider returned duplicate project ID
Error message
workspace provider {provider_id:?} returned duplicate project ID {id:?} What it means
Projects are collected into a `BTreeMap` keyed by ID; inserting an ID that already exists means two projects collide, so the collector bails. Within one provider, a provider should never return the same project ID twice, and this check enforces that per provider.
Solutions
- Deduplicate discovered projects inside the provider before returning them
- Skip already-seen IDs when scanning (track a visited set by canonical path)
- Fix the provider scan so each project is emitted exactly once
Example fix
// before
for dir in dirs {
discovered.push(make_project(dir));
}
// after
let mut seen = HashSet::new();
for dir in dirs {
let p = make_project(dir);
if seen.insert(p.id.clone()) {
discovered.push(p);
}
} Defensive patterns
Strategy: validation
Validate before calling
let mut seen = std::collections::HashSet::new(); discovered.retain(|p| seen.insert(p.id.clone()));
Try / catch
match collect_projects(provider) {
Ok(ps) => ps,
Err(e) if e.to_string().contains("duplicate project ID") => {
eprintln!("provider emitted the same project twice; dedupe before returning");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Track visited canonical paths when scanning directories for projects
- Deduplicate by project ID inside the provider before returning
- Beware symlinks and case-insensitive filesystems causing double discovery
When it happens
Trigger: A single provider's `collect_provider_projects` returns two projects with identical `id` fields (e.g. the same project discovered via two metadata files, or a loop building duplicate entries).
Common situations: A provider scanning directories that matches the same package via both a lockfile and a manifest; symlinked directories visited twice; case-insensitive filesystems where two spellings collapse to one ID.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- duplicate workspace provider ID
- workspace provider attributed lockfile to foreign project
- workspace provider attributed lockfile to unknown project
- workspace provider returned project ID ; IDs must use the…
- affected project exists in graph
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/048640f364ccd981.
Report an issue: GitHub.
Appendix: source
Thrown at src/task/workspace.rs:664
provider_errors.insert(provider_id, error);
continue;
}
Err(error) => return Err(error),
};
for mut project in discovered {
let expected_prefix = format!("{provider_id}:");
let Some(local_id) = project.id.as_str().strip_prefix(&expected_prefix) else {
bail!(
"workspace provider {provider_id:?} returned project ID {:?}; IDs must use the {expected_prefix:?} namespace",
project.id
);
};
validate_id_part("project", local_id)?;
project.root = normalize_project_root(&project.id, &project.root)?;
attach_provider_provenance(&mut project, &provider_id);
let id = project.id.clone();
if projects.insert(id.clone(), project).is_some() {
bail!(
"workspace provider {provider_id:?} returned duplicate project ID {id:?}"
);
}
}
}
Ok(Self {
projects,
provider_errors,
})
}
/// Applies explicit project and dependency changes after provider discovery.
pub(crate) fn with_overrides(
mut self,
overrides: &BTreeMap<String, WorkspaceProjectOverride>,
) -> Result<Self> {
let mut removed = BTreeSet::new();View on GitHub (pinned to 533346cc37)