can1357/oh-my-pi · error · Error
Unknown tool: ${tool}
Error message
Unknown tool: ${tool} What it means
downloadTool() looks up the tool's metadata in the TOOLS registry before doing any network work. If the requested name is not a registered ToolName, it throws immediately with the unknown name — a guard against programming errors rather than an environmental failure.
Source
Thrown at packages/coding-agent/src/utils/tools-manager.ts:220
});
if (!response.ok) {
throw new Error(`Failed to download: ${response.status}`);
} else if (!response.body) {
throw new Error("No response body");
}
await writeResponseBody(dest, response.body, downloadSignal);
} catch (err) {
if (isAbortLikeError(err)) {
throw new Error(`Download timed out: ${url}`);
}
throw err;
}
}
// Download and install a tool
async function downloadTool(tool: ToolName, signal?: AbortSignal): Promise<string> {
const config = TOOLS[tool];
if (!config) throw new Error(`Unknown tool: ${tool}`);
const plat = os.platform();
const architecture = os.arch();
// Get latest version
const version = await getLatestVersion(config.repo, signal);
// Get asset name for this platform
const assetName = config.getAssetName(version, plat, architecture);
if (!assetName) {
throw new Error(`Unsupported platform: ${plat}/${architecture}`);
}
// Create tools directory
await fs.promises.mkdir(TOOLS_DIR, { recursive: true });
const downloadUrl = `https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version}/${assetName}`;
const binaryExt = plat === "win32" ? ".exe" : "";View on GitHub (pinned to 9690622007)
Solutions
- Fix the tool name to one of the supported ToolName values defined in TOOLS.
- If using dynamic/config-driven names, validate against the known tool list before calling.
- Upgrade the package if the tool was added in a newer version of the manager.
- Install the missing tool manually and reference it via its system path instead.
Example fix
// before: await toolsManager.path("ripgrep") // throws Unknown tool: ripgrep | // after: await toolsManager.path("rg") // correct registered name Defensive patterns
Strategy: validation
Validate before calling
// validate the tool name against the registry before calling | const SUPPORTED = new Set(["rg", "fd", "sg", "ast-grep"]); if (!SUPPORTED.has(toolName)) throw new Error(`Unsupported tool: ${toolName}`); Type guard
function isKnownTool(name: string): name is ToolName { return (["rg", "fd", "sg", "ast-grep"] as string[]).includes(name); } Try / catch
try { const p = await toolsManager.path(toolName); } catch (err) { if (err.message.startsWith("Unknown tool:")) { /* reject the config entry / prompt user for a valid tool */ } else throw err; } Prevention
- Use the exported ToolName type instead of raw strings.
- Validate config/user-supplied tool names against the registry at load time.
- Keep the tool list in sync when upgrading the package.
- Centralize tool-name constants to avoid typos.
When it happens
Trigger: Calling downloadTool/path/download with a tool name not present in the TOOLS map, e.g. a typo ("ripgrep" instead of "rg") or a tool added upstream but not in this version of the manager.
Common situations: Typos in tool identifiers, code written against a newer/older tool list, dynamic tool names derived from user input or config files containing an unsupported entry.
Related errors
- Unknown search provider: ${id}
- unknown function: {0}
- unknown key binding function: {0}
- No model configured
- Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d664878a51da6d1b.
Report an issue: GitHub.