From 95947f29fec3439578d843cca75bb72afba0dabe Mon Sep 17 00:00:00 2001 From: Vineeth Sai Date: Thu, 27 Aug 2026 09:58:32 -0700 Subject: [PATCH] fix(utils): stop shorten_message_to_fit_limit growing the message when half_length is 0 content[-0:] is content[0:], the whole string, so once new_length // 2 falls to zero the trim returns '..' + content: two characters longer than its input. The loop then spends its whole attempt budget growing the message instead of shrinking it, calling get_token_count on each pass. Spell the empty right half out so the trim converges on '..'. Rebased onto the current staging tip; the test file conflicted only because both sides appended at the end, so both sets of tests are kept. Signed-off-by: Vineeth Sai --- litellm/utils.py | 5 ++++- tests/test_litellm/test_utils.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/litellm/utils.py b/litellm/utils.py index 54f97ccae54..3cf14b274b2 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -7083,7 +7083,10 @@ def shorten_message_to_fit_limit(message, tokens_needed, model: str | None, rais half_length = new_length // 2 left_half = content[:half_length] - right_half = content[-half_length:] + # content[-0:] is content[0:], i.e. the whole string, so a zero half has to be + # spelled out. Otherwise every further attempt prepends ".." to the full content + # and the message grows by two characters instead of shrinking. + right_half = content[-half_length:] if half_length else "" trimmed_content = left_half + ".." + right_half message["content"] = trimmed_content diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index 20e67b902b8..09439216142 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -5635,3 +5635,21 @@ def test_snapshot_exception_for_hook_preserves_suppress_context_flag() -> None: snapshot = _snapshot_exception_for_hook(e) assert snapshot.__suppress_context__ is False assert snapshot.__context__ is e.__context__ + + +def test_shorten_message_to_fit_limit_never_grows_content(): + """A zero half_length must not turn the trim into a two-character prefix. + + `content[-0:]` is `content[0:]`, so with half_length == 0 the "right half" is the + whole string and each attempt returns `".." + content`. The loop then runs its full + attempt budget growing the message two characters at a time. + """ + from litellm.utils import shorten_message_to_fit_limit + + content = "hello world " * 40 + message = {"role": "user", "content": content} + + result = shorten_message_to_fit_limit(message, tokens_needed=1, model="claude-3-5-sonnet-20240620") + + assert len(result["content"]) < len(content) + assert not result["content"].startswith("....")