Skip to content

[BUG]: TypeError in Bedrock instrumentation when tool_input is dict instead of JSON string #16356

@johaywood

Description

@johaywood

Tracer Version(s)

4.3.1

Python Version(s)

3.14

Pip Version(s)

uv

Bug Report

The ddtrace Bedrock instrumentation crashes with a TypeError when processing tool use responses from AWS Bedrock. The issue occurs in ddtrace/llmobs/_integrations/utils.py in the get_final_message_converse_stream_message function.

The function attempts to parse tool_input with json.loads(), but AWS Bedrock sometimes returns tool inputs as already-parsed dict objects rather than JSON strings. This causes the instrumentation to fail with:

TypeError: the JSON object must be str, bytes or bytearray, not dict

Expected Behavior

The instrumentation should handle tool inputs regardless of whether they are:

  • JSON strings (need parsing with json.loads())
  • Already-parsed dict objects (use directly)

Actual Behavior

The instrumentation crashes with TypeError when tool_input is a dict, breaking LLM observability and potentially disrupting the application flow.

Root Cause

In ddtrace/llmobs/_integrations/utils.py, the get_final_message_converse_stream_message function assumes tool_input is always a JSON string:

# Problematic code (approximate line 1448)
tool_input = tool_block.get("input")
tool_args = json.loads(tool_input)  # Fails when tool_input is already a dict

Proposed Fix

Add type checking before attempting to parse:

tool_input = tool_block.get("input")
tool_args = {}

if isinstance(tool_input, dict):
    # Already parsed - use directly
    tool_args = tool_input
elif isinstance(tool_input, str):
    # JSON string - parse it
    try:
        tool_args = json.loads(tool_input)
    except (json.JSONDecodeError, ValueError):
        # Invalid JSON - wrap in dict
        tool_args = {"input": tool_input}
else:
    # Unexpected type - convert to string
    tool_args = {"input": str(tool_input)}

Workaround

We've implemented a monkey-patch that wraps the problematic function with the type checking above. This is a temporary solution until the upstream fix is available.

Reproduction Code

  1. Set up AWS Bedrock with Claude model (Sonnet 4.5)
  2. Enable ddtrace LLM observability:
    from ddtrace.llmobs import LLMObs
    
    LLMObs.enable(
        ml_app="my_app",
        api_key=os.getenv("DD_API_KEY"),
        site="datadoghq.com",
        agentless_enabled=True,
        integrations_enabled=True
    )
  3. Create an agent with tools using the Bedrock Converse API
  4. Invoke the agent with a prompt that triggers tool use
  5. Observe the TypeError when the agent attempts to use a tool

Error Logs

Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/strands/models/bedrock.py", line 770, in _stream
    for chunk in response["stream"]:
  File "/usr/local/lib/python3.14/site-packages/ddtrace/llmobs/_integrations/base_stream_handler.py", line 142, in __iter__
    self._self_handler.process_chunk(chunk, self._self_stream_iter)
  File "/usr/local/lib/python3.14/site-packages/ddtrace/contrib/internal/botocore/services/bedrock.py", line 92, in process_chunk
    stream_processor.send(chunk)
  File "/usr/local/lib/python3.14/site-packages/ddtrace/llmobs/_integrations/bedrock.py", line 325, in _converse_output_stream_processor
    get_final_message_converse_stream_message(current_message, text_content_blocks, tool_content_blocks)
  File "/usr/local/lib/python3.14/site-packages/ddtrace/llmobs/_integrations/utils.py", line 1448, in get_final_message_converse_stream_message
    tool_args = json.loads(tool_input)
                ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/json/__init__.py", line 345, in loads
    raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                    f'not {s.__class__.__name__}')
TypeError: the JSON object must be str, bytes or bytearray, not dict

Libraries in Use

No response

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    MLObsML Observability (LLMObs)bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions