jdx/mise · error
workspace provider returned project ID ; IDs must use the…
Error message
workspace provider {provider_id:?} returned project ID {:?}; IDs must use the {expected_prefix:?} namespace What it means
Each provider must return project IDs already namespaced with its own ID as the prefix (`provider:local`). When a discovered project's ID does not start with `provider_id + ":"`, the collector bails because cross-provider ID lookups and lockfile attribution depend on this convention.
Solutions
- Fix the provider to format project IDs as `format!("{provider_id}:{local_id}")`
- Ensure the provider's `id()` matches the prefix used when constructing project IDs
- Check for a rename: update both the provider ID and the prefix used in project ID generation together
Example fix
// before
project.id = local_id.to_string();
// after
project.id = format!("{}:{}", self.id(), local_id); Defensive patterns
Strategy: try-catch
Validate before calling
for project in discovered {
assert!(project.id.starts_with(&format!("{}:", provider_id)), "project {:?} lacks provider prefix", project.id);
} Type guard
fn in_namespace(id: &str, provider_id: &str) -> bool { id.starts_with(&format!("{provider_id}:")) } Try / catch
match collect_projects(provider) {
Ok(ps) => ps,
Err(e) if e.to_string().contains("namespace") => {
eprintln!("provider returned unprefixed project IDs; fix provider id formatting");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Centralize project-ID construction in one helper that applies the prefix
- Add provider tests asserting returned IDs match the namespace
- When renaming a provider, update ID generation and prefix checks together
When it happens
Trigger: A provider implementation (in `collect_provider_projects`) returns projects whose `id` field was not formatted as `{provider_id}:{local_id}` — e.g. it set the raw local name or a differently-prefixed ID.
Common situations: Writing a custom provider that forgets to prefix IDs; a provider renamed (ID changed) while its project discovery code still builds the old prefix; concatenating the prefix with the wrong separator.
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
- workspace provider attributed lockfile to foreign project
- duplicate workspace provider ID
- workspace provider attributed lockfile to unknown project
- workspace provider returned duplicate project ID
- affected project exists in graph
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/71e1e13b2cc3c5b6.
Report an issue: GitHub.
Appendix: source
Thrown at src/task/workspace.rs:654
for (provider_id, provider) in providers {
let discovered = match provider.discover_with_context(workspace_root, context) {
Ok(projects) => projects,
Err(error) if skip_provider_errors => {
let error = format!("{error:#}");
warn!(
"failed to discover {provider_id} workspace projects at {}; inferred tasks \
and upstream task dependencies from this provider are unavailable: {error}",
workspace_root.display(),
);
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,View on GitHub (pinned to 533346cc37)