jdx/mise · error

duplicate workspace provider ID

Error message

duplicate workspace provider ID {provider_id:?}

What it means

When collecting workspace projects, mise gathers providers into a map and sorts them by ID; this error fires if two entries share the same provider ID after validation. It guards an internal invariant: each provider should appear exactly once, so duplicates indicate a misconfigured or buggy provider registry.

Solutions

  1. Remove the duplicate provider declaration, keeping one
  2. Check for the same provider defined in both global (~/.config/mise/config.toml) and project mise.toml and deduplicate
  3. If the ID comes from config keys, look for aliases resolving to the same underlying provider ID

Example fix

// before
providers = ["npm", "npm"]
// after
providers = ["npm"]
Defensive patterns

Strategy: validation

Validate before calling

let mut seen = std::collections::HashSet::new();
for id in provider_ids {
    if !seen.insert(id) {
        return Err(anyhow!("duplicate provider id {id}"));
    }
}

Try / catch

match collect_providers(config) {
    Ok(p) => p,
    Err(e) if e.to_string().contains("duplicate workspace provider ID") => {
        eprintln!("dedupe provider declarations across config files");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Registering the same provider ID twice in the workspace provider list, e.g. the same provider name declared in multiple config sources or a provider added twice programmatically.

Common situations: Duplicate provider entries across global and project mise.toml; a plugin listed under two names that resolve to the same ID; repeated registration during config layering.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/a7640de42038990e. Report an issue: GitHub.

Appendix: source

Thrown at src/task/workspace.rs:630

        Ok(graph)
    }

    fn collect_provider_projects(
        providers: &[&dyn WorkspaceProvider],
        workspace_root: &Path,
        context: &WorkspaceDiscoveryContext,
        skip_provider_errors: bool,
    ) -> Result<WorkspaceProjectGraph> {
        let mut providers = providers
            .iter()
            .map(|provider| (provider.id().to_string(), *provider))
            .collect::<Vec<_>>();
        providers.sort_by(|(left, _), (right, _)| left.cmp(right));

        for (index, (provider_id, _)) in providers.iter().enumerate() {
            validate_id_part("provider", provider_id)?;
            if index > 0 && providers[index - 1].0 == *provider_id {
                bail!("duplicate workspace provider ID {provider_id:?}");
            }
        }

        let mut projects = BTreeMap::new();
        let mut provider_errors = BTreeMap::new();
        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;
                }

View on GitHub (pinned to 533346cc37)