From 697ca56f3194e03bf64a3bf05cedb9849f0b26b7 Mon Sep 17 00:00:00 2001 From: Gautam Kishore Date: Fri, 10 Jul 2026 15:59:29 +0530 Subject: [PATCH 1/2] fix: replace bare raise outside except block with explicit ToolUsageError In _original_tool_calling, a bare raise on the non-dict branch is outside any active exception handler. Python raises RuntimeError instead of ToolUsageError. Fixes #6430 --- lib/crewai/src/crewai/tools/tool_usage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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( From c6daca12552f07c166bc4e2ee1e613a61ff0d62d Mon Sep 17 00:00:00 2001 From: Gautam Kishore Date: Fri, 10 Jul 2026 16:23:16 +0530 Subject: [PATCH 2/2] test: regression test for bare raise on non-dict tool input (#6430) Covers the _original_tool_calling non-dict branch: with raise_error=True it must raise ToolUsageError, not RuntimeError from a bare raise outside an except block. --- lib/crewai/tests/tools/test_tool_usage.py | 30 ++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/crewai/tests/tools/test_tool_usage.py b/lib/crewai/tests/tools/test_tool_usage.py index 9d61c93a9b..ca8b30296f 100644 --- a/lib/crewai/tests/tools/test_tool_usage.py +++ b/lib/crewai/tests/tools/test_tool_usage.py @@ -25,7 +25,7 @@ ) 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.tool_utils import execute_tool_and_check_finality from pydantic import BaseModel, Field import pytest @@ -903,3 +903,31 @@ 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_not_runtime_error(): + """A non-dict tool input with ``raise_error=True`` must surface a + ``ToolUsageError``, not a ``RuntimeError`` from a bare ``raise`` outside an + except block. + + See issue #6430: ``_original_tool_calling`` raised + ``RuntimeError("No active exception to re-raise")`` instead of the intended + tool-arguments error. + """ + tool = RandomNumberTool() + action = MagicMock() + action.tool = "random_number_generator" + # A JSON array validates to a list, not a dict. + action.tool_input = "[1, 2, 3]" + + tool_usage = ToolUsage( + tools_handler=MagicMock(), + tools=[tool], + task=MagicMock(), + function_calling_llm=MagicMock(), + agent=MagicMock(), + action=action, + ) + + with pytest.raises(ToolUsageError): + tool_usage._original_tool_calling("Action: random_number_generator", raise_error=True)