nikivdev/code · error

external CLI tool not found under

Error message

external CLI tool {} not found under {}

What it means

`resolve_external_cli_tool_in_roots` searches the configured root directories for a manifest matching the requested tool id. When zero manifests match, it bails with this error listing all the root paths that were searched.

Solutions

  1. Check the tool id spelling against the manifest's `id` field.
  2. List the roots shown in the message and confirm the manifest exists under one of them with the expected filename (`MANIFEST_NAME`).
  3. Install or link the tool into one of the roots (e.g. via the install/link flow).
  4. Correct your roots configuration to include the directory containing the manifest.

Example fix

// before
let tool = resolver.resolve_external_cli_tool("my-clii", &roots)?;
// after
let tool = resolver.resolve_external_cli_tool("my-cli", &roots)?;
Defensive patterns

Strategy: validation

Validate before calling

fn assert_tool_installed(id: &str, roots: &[PathBuf]) -> Result<(), String> {
    for root in roots {
        let found = walk_manifests(root)?.any(|m| m.id == id);
        if found { return Ok(()); }
    }
    Err(format!("tool {id} not present under any of {:?}", roots))
}

Try / catch

match resolver.resolve_external_cli_tool(id, &roots) {
    Err(e) if e.to_string().contains("not found under") => {
        eprintln!("installing missing tool {id}...");
        installer.install(id)?;
        resolver.resolve_external_cli_tool(id, &roots)
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling `resolve_external_cli_tool(id, roots)` (or `resolves_manifest_from_roots`) where no manifest file under any root declares `id = "<requested id>"`.

Common situations: Typo in the tool id; tool never installed/linked into a root; manifest placed in the wrong directory or with the wrong filename; roots configured to a path that doesn't contain the tool.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/e204dcaa1cbc137a. Report an issue: GitHub.

Appendix: source

Thrown at src/external_cli.rs:375

) -> Result<ResolvedExternalCliTool> {
    let mut matches = Vec::new();

    for root in roots {
        for candidate in candidate_manifest_paths(root) {
            let manifest = read_manifest(&candidate)?;
            if manifest.id == id {
                matches.push(resolved_from_manifest(
                    candidate,
                    manifest,
                    ExternalCliResolutionKind::DevRoot,
                    None,
                )?);
            }
        }
    }

    match matches.len() {
        0 => bail!(
            "external CLI tool {} not found under {}",
            id,
            roots
                .iter()
                .map(|path| path.display().to_string())
                .collect::<Vec<_>>()
                .join(", ")
        ),
        1 => Ok(matches.remove(0)),
        _ => {
            let locations = matches
                .iter()
                .map(|tool| tool.manifest_path.display().to_string())
                .collect::<Vec<_>>()
                .join(", ");
            bail!(
                "multiple external CLI manifests matched {}: {}",
                id,

View on GitHub (pinned to a747e741ae)