{"record":{"id":"5db22a8018b00849","repo":"nikivdev/code","slug":"multiple-external-cli-manifests-matched","errorCode":null,"errorMessage":"multiple external CLI manifests matched {}: {}","messagePattern":"multiple external CLI manifests matched (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/external_cli.rs","lineNumber":391,"sourceCode":"\n    match matches.len() {\n        0 => bail!(\n            \"external CLI tool {} not found under {}\",\n            id,\n            roots\n                .iter()\n                .map(|path| path.display().to_string())\n                .collect::<Vec<_>>()\n                .join(\", \")\n        ),\n        1 => Ok(matches.remove(0)),\n        _ => {\n            let locations = matches\n                .iter()\n                .map(|tool| tool.manifest_path.display().to_string())\n                .collect::<Vec<_>>()\n                .join(\", \");\n            bail!(\n                \"multiple external CLI manifests matched {}: {}\",\n                id,\n                locations\n            )\n        }\n    }\n}\n\nfn resolved_from_link_record(\n    record: &ExternalCliLinkRecord,\n    registration_path: Option<PathBuf>,\n) -> Result<ResolvedExternalCliTool> {\n    let manifest = read_manifest(&record.manifest_path)?;\n    if manifest.id != record.id {\n        bail!(\n            \"external CLI link {} points to manifest with mismatched id {}\",\n            record.id,\n            manifest.id","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/external_cli.rs#L373-L409","documentation":"`resolve_external_cli_tool_in_roots` requires tool ids to resolve uniquely. When more than one manifest under the searched roots declares the same id, resolution is ambiguous and the error lists every matching manifest path.","triggerScenarios":"Calling `resolve_external_cli_tool` (or `resolves_manifest_from_roots`) where two or more manifests under the roots have the same `id` value.","commonSituations":"A tool installed both system-wide (in one root) and locally (in another root); a copy of a manifest left in a test/sandbox directory that is also a root; duplicate manifests from re-running an installer into different roots.","solutions":["Remove or rename the duplicate manifest so only one manifest with that id remains across the roots.","Narrow the `roots` list passed to resolution so only the intended root is searched.","Change the `id` in one of the manifests if they are genuinely different tools.","Delete the stale copy left by a previous install."],"exampleFix":"// before\nlet roots = vec![system_root, local_root, stale_sandbox_root];\n// after\nlet roots = vec![local_root];","handlingStrategy":"validation","validationCode":"fn assert_unique_ids(roots: &[PathBuf]) -> Result<(), String> {\n    let mut seen: HashMap<String, PathBuf> = HashMap::new();\n    for root in roots {\n        for m in walk_manifests(root)? {\n            if let Some(prev) = seen.insert(m.id.clone(), m.path.clone()) {\n                return Err(format!(\"duplicate id {} at {:?} and {:?}\", m.id, prev, m.path));\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match resolver.resolve_external_cli_tool(id, &roots) {\n    Err(e) if e.to_string().contains(\"multiple external CLI manifests\") => {\n        eprintln!(\"{e}; narrowing roots to the local install\");\n        resolver.resolve_external_cli_tool(id, &[local_root.clone()])\n    }\n    other => other,\n}","preventionTips":["Keep one install location per tool id; delete stale copies.","Use precedence (e.g. local root first, alone) instead of overlapping roots.","Audit roots for duplicate ids in CI.","Namespace ids per project to avoid collisions between tools."],"tags":["external-cli","ambiguity","configuration"],"backgroundTag":"ambiguous-tool-id","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}