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

  1. Retry with a tool name that is listed in the child's visible tool catalog
  2. Fix the child's policy/allow-list so the needed tool is included in its catalog
  3. Check for tool renames between versions and use the current name
  4. 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

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


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)