crewAIInc/crewAI · error · MergeAgentHandlerToolError
Tool execution failed: {e!s}
Error message
Tool execution failed: {e!s} What it means
The catch-all in MergeAgentHandlerTool._run: any exception that is not already a MergeAgentHandlerToolError (those are re-raised untouched) gets logged and re-wrapped as "Tool execution failed: ..." with the original as __cause__. It fires during parsing of the MCP response content or while navigating the result structure — e.g. unexpected content shapes, missing keys, or JSON shape surprises.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/merge_agent_handler_tool/merge_agent_handler_tool.py:142
params={"name": self.tool_name, "arguments": kwargs},
)
if "result" in result and "content" in result["result"]:
content = result["result"]["content"]
if content and len(content) > 0:
text_content = content[0].get("text", "")
try:
return json.loads(text_content)
except json.JSONDecodeError:
return text_content
return result
except MergeAgentHandlerToolError:
raise
except Exception as e:
logger.error(f"Unexpected error executing tool {self.tool_name}: {e!s}")
raise MergeAgentHandlerToolError(f"Tool execution failed: {e!s}") from e
@classmethod
def from_tool_name(
cls,
tool_name: str,
tool_pack_id: str,
registered_user_id: str,
base_url: str = "https://ah-api.merge.dev",
**kwargs: Any,
) -> te.Self:
"""
Create a MergeAgentHandlerTool from a tool name.
Args:
tool_name: Name of the tool (e.g., "linear__create_issue")
tool_pack_id: UUID of the Tool Pack
registered_user_id: UUID of the registered user
base_url: Base URL for Agent Handler API (defaults to production)View on GitHub (pinned to 754d7323be)
Solutions
- Inspect e.__cause__ (and the log line) — it names the real underlying exception
- Call the same tool via a raw tools/call request and print the full JSON to see the actual content shape
- Pin/verify the tool pack version if the response format regressed; report schema changes to the pack owner
- Handle unexpected content types gracefully on your side (e.g. default to str(result) instead of assuming text)
Example fix
# before
result = tool._run(query="acme") # Tool execution failed: KeyError 'text'
# after
try:
result = tool._run(query="acme")
except MergeAgentHandlerToolError as e:
logging.error("underlying cause: %r", e.__cause__)
raise Defensive patterns
Strategy: try-catch
Validate before calling
def parse_mcp_content(result: dict):
content = result.get("result", {}).get("content", [])
if content and isinstance(content[0], dict) and "text" in content[0]:
import json
try:
return json.loads(content[0]["text"])
except json.JSONDecodeError:
return content[0]["text"]
return result Try / catch
try:
result = tool._run(**kwargs)
except MergeAgentHandlerToolError as e:
cause = e.__cause__
logging.error("tool call failed; cause=%r", cause)
if isinstance(cause, (KeyError, TypeError)):
# response shape changed — inspect raw tools/call output
dump_raw_response()
raise Prevention
- Log e.__cause__ — the wrapper hides the real exception type
- Pin tool pack versions when response formats matter
- Smoke-test each tool after pack updates
When it happens
Trigger: The remote tool returns a content array whose first element has no 'text'; tools/call returns an unexpected result envelope; KeyErrors while walking result["result"]["content"]; unexpected types from json.loads.
Common situations: Remote tool pack updated and changed its response format; a remote tool returning error content instead of text; edge-case responses (empty content list).
Related errors
- Failed to load Tool Pack: {e!s}
- AGENT_HANDLER_API_KEY environment variable is required. Set
- API Error: {error_msg}
- Failed to communicate with Agent Handler API: {e!s}
- Failed to fetch tools from Agent Handler Tool Pack
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/f6c20dceb33e936a.
Report an issue: GitHub.