Skip to content

Fix: malformed tool call transformation in bedrock - #19198

Merged
Sameerlite merged 2 commits into
mainfrom
litellm_handle_malformed_tool_bedrock
Jan 16, 2026
Merged

Fix: malformed tool call transformation in bedrock#19198
Sameerlite merged 2 commits into
mainfrom
litellm_handle_malformed_tool_bedrock

Conversation

@Sameerlite

Copy link
Copy Markdown
Contributor

Relevant issues

Fixes #18667

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Type

🐛 Bug Fix

Changes

@vercel

vercel Bot commented Jan 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
litellm Ready Ready Preview, Comment Jan 16, 2026 11:36am

Review with Vercel Agent

Comment on lines +3244 to +3245
f"Malformed JSON in tool call arguments for tool '{name}': {str(e)}. "
f"Storing as raw string to allow conversation to continue."

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expression logs
sensitive data (password)
as clear text.
This expression logs
sensitive data (secret)
as clear text.
This expressi

Copilot Autofix

AI 7 months ago

At a high level, the fix is to ensure that any logging or error/exception messages do not contain secret material: API keys, passwords, cloud credentials, or raw tool arguments. Instead, logs should contain only high‑level context (e.g., which tool failed, the model name, or that a key was missing) and, if necessary, redacted/masked versions of sensitive values. Also, helper structures like litellm_params that purposely store secrets for runtime behavior should not be blindly stringified or logged.

For the concrete sink in litellm/litellm_core_utils/prompt_templates/factory.py, we can safely change the log message so that it no longer interpolates potentially tainted data. The current warning logs the tool function name and exception detail:

verbose_logger.warning(
    f"Malformed JSON in tool call arguments for tool '{name}': {str(e)}. "
    f"Storing as raw string to allow conversation to continue."
)

To avoid leaking any part of the untrusted path (and still be useful for debugging), we can:

  • Log a generic message that does not include the tool name or parsed content.
  • Optionally include the exception type or a generic error tag, which is not secret.

This change preserves functionality (we still detect parsing errors, fall back to raw string arguments, and log that behavior) while eliminating the possibility of logging secret values coming from tool names/arguments.

No other files need explicit edits for this particular fix because the only explicit sink shown is in factory.py, and we are not allowed to alter external logging behavior in the snippets we haven’t seen. The various get_* and _get_openai_compatible_provider_info functions only construct values and don’t themselves log secrets in the displayed code.

Concretely:

  • In litellm/litellm_core_utils/prompt_templates/factory.py, in _convert_to_bedrock_tool_call_invoke, replace the verbose_logger.warning string with a generic message that omits {name} and str(e) details that come from tainted data.
  • No imports, method signatures, or call sites need to change.

Suggested changeset 1
litellm/litellm_core_utils/prompt_templates/factory.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/litellm/litellm_core_utils/prompt_templates/factory.py b/litellm/litellm_core_utils/prompt_templates/factory.py
--- a/litellm/litellm_core_utils/prompt_templates/factory.py
+++ b/litellm/litellm_core_utils/prompt_templates/factory.py
@@ -3239,10 +3239,12 @@
                     # Try to parse the arguments JSON
                     try:
                         arguments_input = json.loads(arguments)
-                    except json.JSONDecodeError as e:
+                    except json.JSONDecodeError:
+                        # Log a generic message without including tool arguments or names,
+                        # to avoid leaking potentially sensitive data.
                         verbose_logger.warning(
-                            f"Malformed JSON in tool call arguments for tool '{name}': {str(e)}. "
-                            f"Storing as raw string to allow conversation to continue."
+                            "Malformed JSON in tool call arguments. "
+                            "Storing original arguments string to allow conversation to continue."
                         )
                         arguments_input = arguments
                 
EOF
@@ -3239,10 +3239,12 @@
# Try to parse the arguments JSON
try:
arguments_input = json.loads(arguments)
except json.JSONDecodeError as e:
except json.JSONDecodeError:
# Log a generic message without including tool arguments or names,
# to avoid leaking potentially sensitive data.
verbose_logger.warning(
f"Malformed JSON in tool call arguments for tool '{name}': {str(e)}. "
f"Storing as raw string to allow conversation to continue."
"Malformed JSON in tool call arguments. "
"Storing original arguments string to allow conversation to continue."
)
arguments_input = arguments

Copilot is powered by AI and may make mistakes. Always verify output.
merge main in malformed tool call PR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: AWS Bedrock: Malformed JSON in LLM-generated tool call arguments causes subsequent conversation requests to fail

2 participants