jdx/mise · error

duplicate workspace provider ID {provider_id:?}

Error message

duplicate workspace provider ID {provider_id:?}

What it means

mise's workspace loader validates that every workspace provider has a unique ID before collecting the projects each provider discovers. After sorting providers by ID, adjacent entries with the same ID indicate the configuration registered the same provider twice. The library bails out during workspace construction rather than silently merging or shadowing providers.

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 afd2eddd3a)

Solutions

  1. Find the two provider entries with the same ID in your workspace config and rename one so every provider ID is unique.
  2. If config is generated/merged, deduplicate provider entries before writing the config file.
  3. Run `mise doctor` / check the rendered workspace config to confirm which providers are registered and their IDs.

Example fix

// before (mise.toml)
[[workspace.providers]]
id = "monorepo"
[[workspace.providers]]
id = "monorepo"

// after
[[workspace.providers]]
id = "monorepo"
[[workspace.providers]]
id = "vendor"
Defensive patterns

Strategy: validation

Validate before calling

let ids: Vec<_> = config.workspace_providers.iter().map(|p| p.id.clone()).collect();
if ids.len() != ids.iter().collect::<std::collections::BTreeSet<_>>().len() {
    return Err("duplicate workspace provider IDs in config");
}

Prevention

When it happens

Trigger: Building/refreshing a Workspace when the collection of (provider_id, provider) pairs contains two entries whose provider IDs are equal, e.g. two workspace providers declared with the same id in config.

Common situations: Copy-pasting a provider block in a mise.toml workspace config and forgetting to change its id; merging config files that each register a provider with the same id; tooling generating provider entries programmatically that collides on id.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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