From 7400c1b1fa8e96e35a8087a3c1fa1e9bb428f464 Mon Sep 17 00:00:00 2001 From: Dantuluri Surya Narayana Raju Date: Sun, 17 May 2026 17:27:17 +0530 Subject: [PATCH] fix: handle image_url=None in token_counter to prevent ValueError crash --- litellm/litellm_core_utils/token_counter.py | 5 ++- .../litellm_core_utils/test_token_counter.py | 32 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/token_counter.py b/litellm/litellm_core_utils/token_counter.py index e6a68de07e9..5175d884a64 100644 --- a/litellm/litellm_core_utils/token_counter.py +++ b/litellm/litellm_core_utils/token_counter.py @@ -585,7 +585,8 @@ def _count_image_tokens( Count tokens for an image_url content block. Args: - image_url: The image URL data - can be a string URL or dict with 'url' and 'detail' + image_url: The image URL data - can be a string URL or dict with 'url' and 'detail'. + None is treated as an unknown image and returns the default token count. use_default_image_token_count: Whether to use default image token counts Returns: @@ -594,6 +595,8 @@ def _count_image_tokens( Raises: ValueError: If image_url is invalid type or detail value is invalid """ + if image_url is None: + return DEFAULT_IMAGE_TOKEN_COUNT if isinstance(image_url, dict): detail = image_url.get("detail", "auto") if detail not in ["low", "high", "auto"]: diff --git a/tests/test_litellm/litellm_core_utils/test_token_counter.py b/tests/test_litellm/litellm_core_utils/test_token_counter.py index 3aa5f012467..430d97f48e5 100644 --- a/tests/test_litellm/litellm_core_utils/test_token_counter.py +++ b/tests/test_litellm/litellm_core_utils/test_token_counter.py @@ -908,6 +908,38 @@ def test_token_counter_with_image_url(): ), f"Expected detail validation error, got: {e}" +def test_token_counter_image_url_none(): + """ + Regression test: token_counter must not raise ValueError when a content + block has {"type": "image_url", "image_url": None}. + + Previously _count_image_tokens() reached its final else-branch and raised: + ValueError: Invalid image_url type: NoneType. Expected str or dict with 'url' field. + + After the fix, None is treated as an unknown image and the default token + count (DEFAULT_IMAGE_TOKEN_COUNT = 250) is returned so callers are not + disrupted by a None value in an otherwise valid message list. + """ + from litellm.constants import DEFAULT_IMAGE_TOKEN_COUNT + + messages = [ + { + "role": "user", + "content": [ + {"type": "text", "text": "hello"}, + {"type": "image_url", "image_url": None}, + ], + } + ] + + tokens = token_counter(model="gpt-4-vision-preview", messages=messages) + assert tokens > 0, f"Expected positive token count, got {tokens}" + assert tokens >= DEFAULT_IMAGE_TOKEN_COUNT, ( + f"Expected at least DEFAULT_IMAGE_TOKEN_COUNT={DEFAULT_IMAGE_TOKEN_COUNT} " + f"tokens due to the None image_url fallback, got {tokens}" + ) + + def test_token_counter_with_thinking_content(): """ Test that _count_content_list() correctly handles Claude's extended thinking content blocks.