Skip to content

fix(bedrock): degrade gracefully on truncated tool-call arguments instead of failing the request - #32685

Closed
arashne wants to merge 2 commits into
BerriAI:litellm_internal_stagingfrom
arashne:fix/bedrock-truncated-tool-args-degrade
Closed

fix(bedrock): degrade gracefully on truncated tool-call arguments instead of failing the request#32685
arashne wants to merge 2 commits into
BerriAI:litellm_internal_stagingfrom
arashne:fix/bedrock-truncated-tool-args-degrade

Conversation

@arashne

@arashne arashne commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Withdrawing — we're handling this case on the client side instead. Thanks for the project.

…tead of failing the request

A provider stream that ends mid-tool-call leaves a history item whose
arguments string is truncated JSON. split_concatenated_json_objects raised
JSONDecodeError on it, so _convert_to_bedrock_tool_call_invoke failed the
whole request - and since every later turn replays the conversation, one
truncated tool call permanently poisons the session (#18667 reported this
class; the concatenated-objects fix in #20543 did not cover truncation).

split_concatenated_json_objects now stops at an unparseable tail and returns
the complete objects parsed before it; the existing empty-result fallback in
_convert_to_bedrock_tool_call_invoke then emits toolUse.input={} so the
paired toolResult stays addressable and the conversation continues.
@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a deterministic request-poisoning bug where a Bedrock ConverseStream that ends mid-tool-call leaves a truncated JSON arguments string in the conversation history, causing every subsequent replay of that conversation to hard-fail with a JSONDecodeError. The fix makes split_concatenated_json_objects degrade gracefully — catching the decode error, emitting a verbose_logger.warning, and returning whatever complete objects were parsed — so the caller falls through to input={} rather than crashing.

  • common_utils.py: Single try/except wrapping decoder.raw_decode; on failure logs parse position, error, and object count, then breaks. The existing empty-result fallback in _convert_to_bedrock_tool_call_invoke (the function's only caller) handles input={} with no other changes required.
  • Tests: Old "invalid JSON raises" contract test correctly updated to the new degrade contract; four new tests cover the splitter (truncated-single, salvage-prefix) and the Bedrock converter (exact production truncation shape, salvage before truncated tail).

Confidence Score: 5/5

Safe to merge — the change is a minimal, targeted catch-and-log in a single function with one production caller, and the existing fallback in that caller already handles the empty-result case correctly.

The fix is a three-line try/except replacing a bare raw_decode call. The pre-existing if parsed_objects: / arguments_dict = {} fallback in _convert_to_bedrock_tool_call_invoke (the sole production caller) is unmodified and correctly handles the empty-list result. The updated test contract change is intentional and correct — the old 'raises' assertion described the broken behavior, not a regression guard. New tests cover the exact production truncation shape, partial salvage, and end-to-end Bedrock conversion, providing solid regression coverage for the fixed path.

No files require special attention.

Important Files Changed

Filename Overview
litellm/litellm_core_utils/prompt_templates/common_utils.py Wraps the inner decoder.raw_decode call in a try/except; on JSONDecodeError logs a warning and breaks instead of propagating. Minimal, targeted fix with clear logging.
tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_common_utils.py Old "invalid JSON raises" test renamed and corrected to match the new degrade contract; two new splitter tests cover truncated-single-object and partial-salvage cases.
tests/test_litellm/litellm_core_utils/prompt_templates/test_litellm_core_utils_prompt_templates_factory.py Two new end-to-end tests for _convert_to_bedrock_tool_call_invoke: exact production-truncation shape degrades to input={}, and salvage of a complete object before a truncated tail.

Reviews (2): Last reviewed commit: "log a warning when an unparseable tool-c..." | Re-trigger Greptile

Comment thread litellm/litellm_core_utils/prompt_templates/common_utils.py
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing arashne:fix/bedrock-truncated-tool-args-degrade (f3cff16) with litellm_internal_staging (bf02a4a)

Open in CodSpeed

@arashne

arashne commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

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.

1 participant