From 03f8398cf3e2f9be9090bbb88ccbe83a8f109008 Mon Sep 17 00:00:00 2001 From: Zelys Date: Sat, 4 Apr 2026 17:39:10 -0500 Subject: [PATCH] Add warning log when tool input JSON parsing fails When a model returns malformed tool input that cannot be parsed as JSON, the SDK silently falls back to an empty dict. This adds a warning log with the tool name and the first 200 characters of the raw input to aid debugging. 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..f304eda7d 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( + "tool_name=<%s> raw_input=<%s> | failed to parse tool input as JSON; falling back to empty dict", + current_tool_use.get("name"), + current_tool_use["input"][:200], + ) 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..ff82ce76c 100644 --- a/tests/strands/event_loop/test_streaming.py +++ b/tests/strands/event_loop/test_streaming.py @@ -527,6 +527,25 @@ def test_handle_content_block_stop(state, exp_updated_state): assert tru_updated_state == exp_updated_state +def test_handle_content_block_stop_invalid_json_logs_warning(caplog): + state = { + "content": [], + "current_tool_use": {"toolUseId": "123", "name": "my_tool", "input": "not valid json"}, + "text": "", + "reasoningText": "", + "citationsContent": [], + "redactedContent": b"", + } + + import logging + + with caplog.at_level(logging.WARNING, logger="strands.event_loop.streaming"): + tru_updated_state = strands.event_loop.streaming.handle_content_block_stop(state) + + assert tru_updated_state["content"] == [{"toolUse": {"toolUseId": "123", "name": "my_tool", "input": {}}}] + assert any("failed to parse tool input as JSON" in record.message for record in caplog.records) + + def test_handle_message_stop(): event: MessageStopEvent = {"stopReason": "end_turn"}