fix(vertex_ai/gemini): raise BadRequestError when image_url or url fi… (#24550)

Squash-merged by litellm-agent from krisxia0506's PR.
This commit is contained in:
Kris Xia 2026-05-13 15:00:54 +08:00 • committed by Sameer Kankute
parent 28e6a911e9
commit f524b10c08
No known key found for this signature in database
2 changed files with 70 additions and 5 deletions

View file

@ -351,15 +351,28 @@ def _gemini_convert_messages_with_history( # noqa: PLR0915
img_element = element
format: Optional[str] = None
media_resolution_enum: Optional[Dict[str, str]] = None
if isinstance(img_element["image_url"], dict):
image_url = img_element["image_url"]["url"]
format = img_element["image_url"].get("format")
detail = img_element["image_url"].get("detail")
raw_image_url = img_element.get("image_url")
if raw_image_url is None:
raise litellm.BadRequestError(
message="Invalid message content: element type is 'image_url' but 'image_url' field is missing ",
model=model,
llm_provider="vertex_ai",
)
if isinstance(raw_image_url, dict):
image_url = raw_image_url.get("url")
if image_url is None:
raise litellm.BadRequestError(
message="Invalid message content: element type is 'image_url' but 'url' field is missing inside 'image_url' ",
model=model,
llm_provider="vertex_ai",
)
format = raw_image_url.get("format")
detail = raw_image_url.get("detail")
media_resolution_enum = (
_convert_detail_to_media_resolution_enum(detail)
)
else:
image_url = img_element["image_url"]
image_url = raw_image_url
_part = _process_gemini_media(
image_url=image_url,
format=format,

View file

@ -0,0 +1,52 @@
import pytest
from typing import List, cast
import litellm
from litellm.llms.vertex_ai.gemini.transformation import (
_gemini_convert_messages_with_history,
)
from litellm.types.llms.openai import AllMessageValues
def test_missing_image_url_field_raises_bad_request_error():
"""When element type is 'image_url' but 'image_url' field is missing, a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url"}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'image_url' field is missing" in str(exc_info.value)
def test_missing_url_inside_image_url_dict_raises_bad_request_error():
"""When image_url is a dict but 'url' key is absent, a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url", "image_url": {"detail": "high"}}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'url' field is missing inside" in str(exc_info.value)
def test_explicit_null_image_url_raises_bad_request_error():
"""When image_url key is present but explicitly null, a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url", "image_url": None}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'image_url' field is missing" in str(exc_info.value)
def test_empty_dict_image_url_raises_bad_request_error():
"""When image_url is an empty dict (no url), a BadRequestError is raised."""
messages = cast(
List[AllMessageValues],
[{"role": "user", "content": [{"type": "image_url", "image_url": {}}]}],
)
with pytest.raises(litellm.BadRequestError) as exc_info:
_gemini_convert_messages_with_history(messages, model="gemini-1.5-pro")
assert "'url' field is missing inside" in str(exc_info.value)