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.
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)
Solutions
- Check the tool id spelling against the manifest's `id` field.
- List the roots shown in the message and confirm the manifest exists under one of them with the expected filename (`MANIFEST_NAME`).
- Install or link the tool into one of the roots (e.g. via the install/link flow).
- 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
- Verify the tool id spelling against the manifest `id` field.
- Run an install/link step before resolution in scripts and CI.
- Keep roots configuration in one place and assert required roots exist at startup.
- Smoke-test tool resolution as part of environment setup.
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
- {} has no exec.run argv in {}
- multiple external CLI manifests matched {}: {}
- {} does not contain {}
- Missing GEMINI_API_KEY/GOOGLE_API_KEY (set env var or add to
- Session '{}' not found in saved sessions
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/e204dcaa1cbc137a.
Report an issue: GitHub.