Hmbown/CodeWhale · error · anyhow::Error
Tool is not in this child's policy-filtered catalog
Error message
Tool {name} is not in this child's policy-filtered catalog What it means
When dispatching a non-tool_search call, the child looks up the named tool in the policy-filtered surface catalog to learn whether it is deferred. If the tool is not present in the catalog at all, this error is returned — the child's policy filtered it out or it simply is not part of this child's tool surface. Only tools present in the catalog can be dispatched, and deferred ones must additionally be hydrated (active) first.
Solutions
- Retry with a tool name that is listed in the child's visible tool catalog
- Fix the child's policy/allow-list so the needed tool is included in its catalog
- Check for tool renames between versions and use the current name
- If the tool is deferred but present, it must be activated via tool_search first — a different error path than this one
Example fix
// before: child calls a parent-only tool
{"name": "deploy", ...} // not in child's catalog
// after: child uses its own catalog tool and reports back
{"name": "read", "input": {"path": "deploy/plan.md"}} Defensive patterns
Strategy: type-guard
Validate before calling
let in_catalog = child.catalog.iter().any(|t| t.name == name);
if !in_catalog {
return Err(format!("{name} is not available to this child"));
} Type guard
fn tool_in_catalog(child: &SubAgent, name: &str) -> bool {
child.catalog.iter().any(|t| t.name == name)
} Try / catch
match child.call_tool(name, input) {
Err(e) if e.to_string().contains("policy-filtered catalog") =>
Err(anyhow!("{name} is not part of this child's tool surface; use a listed tool")),
other => other,
} Prevention
- Derive the model's tool list only from the child's own catalog, never the parent's
- Review allow/deny policy when a child reports missing tools
- Check for tool renames after version upgrades
When it happens
Trigger: A sub-agent invoking a tool name that does not appear in its policy-filtered catalog — the name was filtered out by the child's allow/deny policy, belongs to the parent but not the child, or is misspelled/renamed.
Common situations: A model guessing at tool names it saw in the parent's system prompt but not in the child's catalog; policy changes (deny rules, agent-type defaults) removing a tool mid-session; version drift renaming tools between catalog construction and dispatch.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Tool is not in this child's catalog
- Sub-agent requested unavailable tools
- Tool could not enter the bounded child toolbox; use…
- Tool not allowed for this sub-agent
- agent action=claim widens an enforced write scope, and the…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/3a1db28ecc62474c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:18129
name: &str,
input: Value,
) -> Result<RichToolResult> {
if is_tool_search_tool(name) {
if !request_active_names.contains(name) {
return Err(anyhow!("Tool {name} is not in this child's catalog"));
}
return surface
.search(name, &input)
.map(|content| RichToolResult::plain(ToolResult::success(content)));
}
let Some(deferred) = surface
.catalog
.iter()
.find(|tool| tool.name == name)
.map(|tool| tool.defer_loading.unwrap_or(false))
else {
return Err(anyhow!(
"Tool {name} is not in this child's policy-filtered catalog"
));
};
if deferred && !request_active_names.contains(name) {
return surface
.hydrate(name)
.map(|content| RichToolResult::plain(ToolResult::success(content)));
}
if !request_active_names.contains(name) {
return Err(anyhow!("Tool {name} is not active for this sub-agent"));
}
let result = self.execute_full(agent_id, tool_id, name, input).await;
if deferred && result.is_ok() {
touch_cached_tool_after_execution(
&surface.catalog,
&mut surface.active_names,
&mut surface.cache,
name,View on GitHub (pinned to 73e0f67d83)