From 257df32d4fc68f57f4d646f3ed8fdd4b8b9fbe57 Mon Sep 17 00:00:00 2001 From: Ratansairohith Date: Sat, 4 Apr 2026 09:11:21 -0700 Subject: [PATCH] fix(streaming): log warning when tool input JSON is malformed Malformed tool input JSON was silently replaced with an empty dict, with no logging. The tool then ran with empty arguments and the model had no indication its JSON was invalid. Added a logger.warning() call before the fallback so operators can detect and diagnose this in production. Fixes #2051 --- src/strands/event_loop/streaming.py | 5 +++++ tests/strands/event_loop/test_streaming.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/strands/event_loop/streaming.py b/src/strands/event_loop/streaming.py index 0a1161135..f5e0e8b02 100644 --- a/src/strands/event_loop/streaming.py +++ b/src/strands/event_loop/streaming.py @@ -279,6 +279,11 @@ def handle_content_block_stop(state: dict[str, Any]) -> dict[str, Any]: try: current_tool_use["input"] = json.loads(current_tool_use["input"]) except ValueError: + logger.warning( + "Failed to parse tool input JSON for '%s': %s", + current_tool_use.get("name", "unknown"), + current_tool_use["input"][:200] if isinstance(current_tool_use.get("input"), str) else "", + ) current_tool_use["input"] = {} tool_use_id = current_tool_use["toolUseId"] diff --git a/tests/strands/event_loop/test_streaming.py b/tests/strands/event_loop/test_streaming.py index 93f8d95f8..ba693485d 100644 --- a/tests/strands/event_loop/test_streaming.py +++ b/tests/strands/event_loop/test_streaming.py @@ -366,6 +366,25 @@ def test_handle_content_block_delta(event: ContentBlockDeltaEvent, event_type, s "redactedContent": b"", }, ), + # Tool Use - Malformed input JSON + ( + { + "content": [], + "current_tool_use": {"toolUseId": "123", "name": "test", "input": "{invalid json}"}, + "text": "", + "reasoningText": "", + "citationsContent": [], + "redactedContent": b"", + }, + { + "content": [{"toolUse": {"toolUseId": "123", "name": "test", "input": {}}}], + "current_tool_use": {}, + "text": "", + "reasoningText": "", + "citationsContent": [], + "redactedContent": b"", + }, + ), # Text ( {