From 0bb488df1ba5cd09fca22bb377f69d6b69f6aff9 Mon Sep 17 00:00:00 2001 From: Tummalapally Sai Aakash Date: Fri, 10 Jul 2026 12:28:51 +0530 Subject: [PATCH] fix(tools): raise ToolUsageError instead of bare raise in _original_tool_calling Fixes #6430. The bare 'raise' in the non-dict-arguments branch of _original_tool_calling had no active exception to re-raise, so Python raised 'RuntimeError: No active exception to re-raise' instead of a meaningful ToolUsageError. Replaced it with an explicit 'raise ToolUsageError(...)' matching the sibling return statement and the pattern used elsewhere in this method. Co-authored-by: Cursor --- lib/crewai/src/crewai/tools/tool_usage.py | 2 +- lib/crewai/tests/tools/test_tool_usage.py | 26 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/crewai/src/crewai/tools/tool_usage.py b/lib/crewai/src/crewai/tools/tool_usage.py index e92ba03eed..c523b2bb43 100644 --- a/lib/crewai/src/crewai/tools/tool_usage.py +++ b/lib/crewai/src/crewai/tools/tool_usage.py @@ -850,7 +850,7 @@ def _original_tool_calling( if not isinstance(arguments, dict): if raise_error: - raise + raise ToolUsageError(f"{I18N_DEFAULT.errors('tool_arguments_error')}") return ToolUsageError(f"{I18N_DEFAULT.errors('tool_arguments_error')}") return ToolCalling( diff --git a/lib/crewai/tests/tools/test_tool_usage.py b/lib/crewai/tests/tools/test_tool_usage.py index 9d61c93a9b..d935c8c6f1 100644 --- a/lib/crewai/tests/tools/test_tool_usage.py +++ b/lib/crewai/tests/tools/test_tool_usage.py @@ -25,7 +25,8 @@ ) from crewai.tools import BaseTool from crewai.tools.tool_calling import ToolCalling -from crewai.tools.tool_usage import ToolUsage +from crewai.tools.tool_usage import ToolUsage, ToolUsageError +from crewai.utilities.i18n import I18N_DEFAULT from crewai.utilities.tool_utils import execute_tool_and_check_finality from pydantic import BaseModel, Field import pytest @@ -903,3 +904,26 @@ def on_finished(source, event): assert len(finished_events) == 0, ( "ToolUsageFinishedEvent should NOT be emitted after ToolUsageErrorEvent" ) + + +def test_original_tool_calling_raises_tool_usage_error_for_non_dict_arguments(): + """Regression test for #6430: non-dict arguments must raise ToolUsageError, + not a bare `raise` (which would raise RuntimeError: No active exception).""" + tool_usage = ToolUsage( + tools_handler=MagicMock(), + tools=[RandomNumberTool()], + task=MagicMock(), + function_calling_llm=MagicMock(), + agent=example_agent, + action=MagicMock(tool="Random Number Generator", tool_input="[]"), + ) + + with patch.object(tool_usage, "_validate_tool_input", return_value=["not", "a", "dict"]): + with pytest.raises(ToolUsageError) as e_info: + tool_usage._original_tool_calling("irrelevant", raise_error=True) + + assert str(e_info.value) == I18N_DEFAULT.errors("tool_arguments_error") + + result = tool_usage._original_tool_calling("irrelevant", raise_error=False) + assert isinstance(result, ToolUsageError) + assert str(result) == I18N_DEFAULT.errors("tool_arguments_error")