{"record":{"id":"a7640de42038990e","repo":"jdx/mise","slug":"duplicate-workspace-provider-id-provider-id","errorCode":null,"errorMessage":"duplicate workspace provider ID {provider_id:?}","messagePattern":"duplicate workspace provider ID (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/workspace.rs","lineNumber":630,"sourceCode":"        Ok(graph)\n    }\n\n    fn collect_provider_projects(\n        providers: &[&dyn WorkspaceProvider],\n        workspace_root: &Path,\n        context: &WorkspaceDiscoveryContext,\n        skip_provider_errors: bool,\n    ) -> Result<WorkspaceProjectGraph> {\n        let mut providers = providers\n            .iter()\n            .map(|provider| (provider.id().to_string(), *provider))\n            .collect::<Vec<_>>();\n        providers.sort_by(|(left, _), (right, _)| left.cmp(right));\n\n        for (index, (provider_id, _)) in providers.iter().enumerate() {\n            validate_id_part(\"provider\", provider_id)?;\n            if index > 0 && providers[index - 1].0 == *provider_id {\n                bail!(\"duplicate workspace provider ID {provider_id:?}\");\n            }\n        }\n\n        let mut projects = BTreeMap::new();\n        let mut provider_errors = BTreeMap::new();\n        for (provider_id, provider) in providers {\n            let discovered = match provider.discover_with_context(workspace_root, context) {\n                Ok(projects) => projects,\n                Err(error) if skip_provider_errors => {\n                    let error = format!(\"{error:#}\");\n                    warn!(\n                        \"failed to discover {provider_id} workspace projects at {}; inferred tasks \\\n                         and upstream task dependencies from this provider are unavailable: {error}\",\n                        workspace_root.display(),\n                    );\n                    provider_errors.insert(provider_id, error);\n                    continue;\n                }","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/task/workspace.rs#L612-L648","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove the duplicate provider declaration, keeping one","Check for the same provider defined in both global (~/.config/mise/config.toml) and project mise.toml and deduplicate","If the ID comes from config keys, look for aliases resolving to the same underlying provider ID"],"exampleFix":"// before\nproviders = [\"npm\", \"npm\"]\n// after\nproviders = [\"npm\"]","handlingStrategy":"validation","validationCode":"let mut seen = std::collections::HashSet::new();\nfor id in provider_ids {\n    if !seen.insert(id) {\n        return Err(anyhow!(\"duplicate provider id {id}\"));\n    }\n}","typeGuard":null,"tryCatchPattern":"match collect_providers(config) {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"duplicate workspace provider ID\") => {\n        eprintln!(\"dedupe provider declarations across config files\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep provider declarations in exactly one config file","Inspect layered config sources to find duplicate definitions","Use a set/map keyed by provider ID when registering providers programmatically"],"tags":["workspace","duplicate","provider"],"backgroundTag":"conflicting-config-options","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}