zeroclaw-labs/zeroclaw · error · anyhow::Error

cli-skills-multiple-locations-path

cli-skills-multiple-locations-path

Error message

skill '{$name}' exists in multiple locations ({$locations}); pass an explicit path to disambiguate

What it means

locate_installed_skill_dir (used by `skills audit` and `skills test --name`) errors when the name matches multiple locations — the same skill installed in several bundles and/or globally. Unlike `skills remove`, the disambiguation asked for here is an explicit path, not a --bundle flag, because audit/test accept arbitrary directories as their source.

Source

Thrown at src/skills/mod.rs:698

        }
    }
    out
}

/// Locate a single installed skill directory by name (across bundles + global),
/// erroring when absent or ambiguous. Used by `audit`/`test`.
fn locate_installed_skill_dir(config: &crate::config::Config, name: &str) -> Result<PathBuf> {
    let mut matches = collect_skill_locations(config, name, None);
    match matches.len() {
        0 => anyhow::bail!("Skill not found: {name}"),
        1 => Ok(matches.remove(0).1),
        _ => {
            let locs = matches
                .iter()
                .map(|(label, _)| label.clone())
                .collect::<Vec<_>>()
                .join(", ");
            anyhow::bail!(
                "{}",
                get_required_cli_string_with_args(
                    "cli-skills-multiple-locations-path",
                    &[("name", name), ("locations", &locs)],
                )
            )
        }
    }
}

/// Render one skill row for `skills list` (name + version + tools + tags).
fn print_skill(skill: &Skill) {
    println!(
        "  {} {} — {}",
        console::style(&skill.name).white().bold(),
        console::style(format!("v{}", skill.version)).dim(),
        skill.description
    );

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Pass the explicit skill directory path as the argument instead of the bare name
  2. Build the path from the labels in the error: bundle:<alias> → that bundle's resolved directory, global → the global skills dir
  3. Or remove/rename the duplicate copies so exactly one location remains

Example fix

# before
zeroclaw skills test --name foo

# after
zeroclaw skills test --name ~/.local/share/zeroclaw/skills/foo
Defensive patterns

Strategy: validation

Validate before calling

// In automation, always pass an explicit directory path to audit/test
// (bundle dirs: resolve from [skill_bundles.<alias>].directory or the default root;
//  global: <data-dir>/skills/<name>)
let path = format!("{data_dir}/skills/{name}");
assert!(Path::new(&path).is_dir(), "use a unique explicit path: {path}");

Prevention

When it happens

Trigger: `skills test --name foo` where foo exists in two bundles, or in a bundle and the global dir; duplicates left after migrating skills between locations.

Common situations: Testing during a global-to-bundle migration; shared skill names across team bundles; verifying one specific copy among duplicates.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/0b52752df117cfef. Report an issue: GitHub.