fix(tools): return structured JSON error data from tool exceptions#6313
fix(tools): return structured JSON error data from tool exceptions#6313AHMEDDEV2004 wants to merge 1 commit into
Conversation
Replace generic "Error executing tool: {e}" strings with structured
JSON containing exception type, message, and retryability hint.
This gives agents the information needed to decide whether to retry,
fix their input, or skip the tool entirely.
Closes crewAIInc#6262
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Summary: This PR changes tool exception handling to return structured JSON error metadata while preserving the existing error prefix.
Risk: Low risk. No exploitable security vulnerabilities were identified; the changes do not add authentication, authorization, data access, network, subprocess, or file-handling attack surfaces.
📝 WalkthroughWalkthroughA new ChangesStructured Tool Error Formatting
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/crewai/src/crewai/utilities/agent_utils.py (1)
1549-1565: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winAlign
ToolUsageErrorEvent.errorwith the new structured error contractThis path formats
resultwithformat_tool_error(e)but still emitsToolUsageErrorEvent(error=e), producing mixed error payload shapes across call paths.Suggested fix
except Exception as e: - result = format_tool_error(e) + structured_error = format_tool_error(e) + result = structured_error raw_tool_result = result if task: task.increment_tools_errors() crewai_event_bus.emit( event_source, event=ToolUsageErrorEvent( tool_name=func_name, tool_args=args_dict, from_agent=agent, from_task=task, agent_key=agent_key, plan_step_number=plan_step_number, plan_step_description=plan_step_description, - error=e, + error=structured_error, ), )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/crewai/src/crewai/utilities/agent_utils.py` around lines 1549 - 1565, The ToolUsageErrorEvent payload is still emitting the raw exception while this path already converts it to the structured form via format_tool_error in agent_utils; update the ToolUsageErrorEvent construction in the exception handler to use the same structured error value as raw_tool_result/result so the error contract is consistent across call paths. Locate the emit call in the except block around ToolUsageErrorEvent and align its error field with the formatted error object rather than passing e directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/crewai/src/crewai/utilities/tool_errors.py`:
- Around line 27-28: The traceback handling in tool error formatting should use
the passed exception’s own traceback instead of relying on ambient exception
state. Update the logic in the utility that builds error details (the block
guarded by include_traceback in the tool error formatter) to format from the
exception object’s __traceback__ rather than calling traceback.format_exc(), so
the recorded traceback is accurate even when not inside an active except block.
---
Outside diff comments:
In `@lib/crewai/src/crewai/utilities/agent_utils.py`:
- Around line 1549-1565: The ToolUsageErrorEvent payload is still emitting the
raw exception while this path already converts it to the structured form via
format_tool_error in agent_utils; update the ToolUsageErrorEvent construction in
the exception handler to use the same structured error value as
raw_tool_result/result so the error contract is consistent across call paths.
Locate the emit call in the except block around ToolUsageErrorEvent and align
its error field with the formatted error object rather than passing e directly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6670a8b3-1c28-4413-ba15-ac5ea44f0e92
📒 Files selected for processing (6)
lib/crewai/src/crewai/agents/crew_agent_executor.pylib/crewai/src/crewai/experimental/agent_executor.pylib/crewai/src/crewai/llm.pylib/crewai/src/crewai/utilities/agent_utils.pylib/crewai/src/crewai/utilities/tool_errors.pylib/crewai/tests/test_tool_errors.py
| if include_traceback: | ||
| error_data["traceback"] = traceback.format_exc(limit=3) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use the passed exception traceback instead of ambient exception state.
On Line 28, traceback.format_exc() can emit NoneType: None if this formatter is called outside an active except block. Format from exception.__traceback__ directly to keep traceback accurate.
Proposed fix
- if include_traceback:
- error_data["traceback"] = traceback.format_exc(limit=3)
+ if include_traceback:
+ error_data["traceback"] = "".join(
+ traceback.format_exception(
+ type(exception), exception, exception.__traceback__, limit=3
+ )
+ )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if include_traceback: | |
| error_data["traceback"] = traceback.format_exc(limit=3) | |
| if include_traceback: | |
| error_data["traceback"] = "".join( | |
| traceback.format_exception( | |
| type(exception), exception, exception.__traceback__, limit=3 | |
| ) | |
| ) |
🧰 Tools
🪛 ast-grep (0.44.0)
[info] 28-28: use jsonify instead of json.dumps for JSON output
Context: json.dumps(error_data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/crewai/src/crewai/utilities/tool_errors.py` around lines 27 - 28, The
traceback handling in tool error formatting should use the passed exception’s
own traceback instead of relying on ambient exception state. Update the logic in
the utility that builds error details (the block guarded by include_traceback in
the tool error formatter) to format from the exception object’s __traceback__
rather than calling traceback.format_exc(), so the recorded traceback is
accurate even when not inside an active except block.
Summary
Closes #6262
When a tool raises an exception, CrewAI currently catches it and returns a generic string like
"Error executing tool: {e}"— discarding the exception type, retryability classification, and structured data that agents need to make informed decisions.This PR replaces all generic error strings with structured JSON containing:
error: true— unambiguous error flagtype— exception class name (e.g."TimeoutError","ValueError")message— original exception messageretryable— boolean hint based on exception type (TrueforTimeoutError,ConnectionError,OSError)Before
After
The
"Error executing tool:"prefix is preserved for backward compatibility with existing parsing logic.Changes
crewai/utilities/tool_errors.py—format_tool_error()utility with retryable classificationagents/crew_agent_executor.py(native tool call handler)experimental/agent_executor.py(3 locations: ReAct loop, parallel tool calls, native tool handler)utilities/agent_utils.py(shared tool execution utility)llm.py(event emissions forLLMCallFailedEventandToolUsageErrorEvent)tests/test_tool_errors.py— 17 unit tests covering all error scenariosDesign Decisions
retryablehint — Lets agents automatically retry transient failures (network, timeout) without wasting iterations on permanent errors (validation, type errors)."Error executing tool:"so any existing regex/startswith checks continue to work.include_traceback=Truefor debugging, but excluded by default to save LLM context window.Test plan
format_tool_error()pytest lib/crewai/tests/agents/) — CI will verify🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes