Skip to content

bug: Malformed tool input JSON silently replaced with empty dict, no logging #2051

@Ratansairohith

Description

@Ratansairohith

Description

In streaming.py, when a model returns invalid JSON as tool input, the ValueError is caught and the input is silently replaced with an empty dict {}. There is no log message or warning.

src/strands/event_loop/streaming.py, lines 279-282:

try:
    current_tool_use["input"] = json.loads(current_tool_use["input"])
except ValueError:
    current_tool_use["input"] = {}

The tool then executes with empty arguments, fails with a missing-parameter error, and the model has no indication that its JSON was malformed. It retries the same broken JSON repeatedly.

This happens most often with smaller models (Ollama, llama.cpp, Mistral local) that produce truncated or syntactically invalid JSON for tool inputs.

Reproduction

Any model that returns invalid tool input JSON. Examples that trigger this:

  • {"query": "test (truncated by max_tokens mid-tool-call)
  • {query: test} (unquoted keys)
  • empty string

All silently become {}.

Suggested fix

Log a warning and return an informative error to the model instead of silently passing {} to the tool:

except ValueError:
    logger.warning("Failed to parse tool input JSON for '%s': %s", current_tool_use.get("name"), current_tool_use["input"])
    current_tool_use["input"] = {"_parse_error": f"Invalid JSON in tool input: {current_tool_use['input'][:200]}"}

This way the tool can detect the parse error, and the model gets feedback that its JSON was malformed rather than thinking the tool itself is broken.

Happy to submit a PR for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions