Skip to content

Commit 257df32

Browse files
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
1 parent 94fc8dd commit 257df32

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

src/strands/event_loop/streaming.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ def handle_content_block_stop(state: dict[str, Any]) -> dict[str, Any]:
279279
try:
280280
current_tool_use["input"] = json.loads(current_tool_use["input"])
281281
except ValueError:
282+
logger.warning(
283+
"Failed to parse tool input JSON for '%s': %s",
284+
current_tool_use.get("name", "unknown"),
285+
current_tool_use["input"][:200] if isinstance(current_tool_use.get("input"), str) else "",
286+
)
282287
current_tool_use["input"] = {}
283288

284289
tool_use_id = current_tool_use["toolUseId"]

tests/strands/event_loop/test_streaming.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,25 @@ def test_handle_content_block_delta(event: ContentBlockDeltaEvent, event_type, s
366366
"redactedContent": b"",
367367
},
368368
),
369+
# Tool Use - Malformed input JSON
370+
(
371+
{
372+
"content": [],
373+
"current_tool_use": {"toolUseId": "123", "name": "test", "input": "{invalid json}"},
374+
"text": "",
375+
"reasoningText": "",
376+
"citationsContent": [],
377+
"redactedContent": b"",
378+
},
379+
{
380+
"content": [{"toolUse": {"toolUseId": "123", "name": "test", "input": {}}}],
381+
"current_tool_use": {},
382+
"text": "",
383+
"reasoningText": "",
384+
"citationsContent": [],
385+
"redactedContent": b"",
386+
},
387+
),
369388
# Text
370389
(
371390
{

0 commit comments

Comments
 (0)