{"record":{"id":"50850122cd12f8ac","repo":"Hmbown/CodeWhale","slug":"tool-name-is-not-in-this-child-s-catalog","errorCode":null,"errorMessage":"Tool {name} is not in this child's catalog","messagePattern":"Tool (.+?) is not in this child's catalog","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":18116,"sourceCode":"    #[cfg(test)]\n    async fn execute(&self, agent_id: &str, name: &str, input: Value) -> Result<String> {\n        self.execute_full(agent_id, \"\", name, input)\n            .await\n            .map(|result| result.result.content)\n    }\n\n    async fn execute_from_surface(\n        &self,\n        agent_id: &str,\n        tool_id: &str,\n        surface: &mut SubAgentToolSurface,\n        request_active_names: &std::collections::HashSet<String>,\n        name: &str,\n        input: Value,\n    ) -> Result<RichToolResult> {\n        if is_tool_search_tool(name) {\n            if !request_active_names.contains(name) {\n                return Err(anyhow!(\"Tool {name} is not in this child's catalog\"));\n            }\n            return surface\n                .search(name, &input)\n                .map(|content| RichToolResult::plain(ToolResult::success(content)));\n        }\n\n        let Some(deferred) = surface\n            .catalog\n            .iter()\n            .find(|tool| tool.name == name)\n            .map(|tool| tool.defer_loading.unwrap_or(false))\n        else {\n            return Err(anyhow!(\n                \"Tool {name} is not in this child's policy-filtered catalog\"\n            ));\n        };\n        if deferred && !request_active_names.contains(name) {\n            return surface","sourceCodeStart":18098,"sourceCodeEnd":18134,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/subagent/mod.rs#L18098-L18134","documentation":"The child's tool dispatch first checks request_active_names before executing; for the tool_search tool itself, if it is not in the active (admitted) name set for this request, the call is refused with this error. A child may only invoke tools actually present in its (policy-filtered, activation-gated) catalog for the current request — nothing is reachable by guessing names.","triggerScenarios":"A sub-agent (or model on its behalf) invoking tool_search when tool_search was not admitted into the request's active tool set — e.g. the parent's policy excluded it or it was never hydrated for this request.","commonSituations":"A model hallucinating/assuming tool_search is always available, a policy filter that stripped it from the child's catalog, or replaying a tool call recorded from a request where it was active.","solutions":["Check the child's policy/allow-list so tool_search is admitted when the child needs deferred-tool discovery","Retry with a tool that is in the child's current catalog (inspect the catalog shown to the model)","If the child does not need discovery, call the concrete tool directly instead of tool_search"],"exampleFix":"// before: calling tool_search when it is not active for the request\n{\"name\": \"tool_search\", \"input\": {\"query\": \"read file\"}}\n// after: use a tool actually in the child's catalog\n{\"name\": \"read\", \"input\": {\"path\": \"src/main.rs\"}}","handlingStrategy":"type-guard","validationCode":"if !child.active_tool_names().contains(\"tool_search\") {\n    return Err(\"tool_search not active for this request\".into());\n}","typeGuard":"fn tool_is_active(child: &SubAgent, name: &str) -> bool {\n    child.request_active_names().contains(name)\n}","tryCatchPattern":"match child.call_tool(name, input) {\n    Err(e) if e.to_string().contains(\"not in this child's catalog\") =>\n        Err(anyhow!(\"pick a tool from the child's visible catalog\")),\n    other => other,\n}","preventionTips":["Only call tools listed in the child's visible catalog for the current request","Keep policy filters consistent so tool_search is admitted when discovery is needed","Do not replay tool calls recorded against a different request's active set"],"tags":["subagent","tools","catalog","policy"],"backgroundTag":"resource-not-found","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}