mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(images): return 400 when /images/edits omits image
aimage_edit required a positional image, so the proxy returned HTTP 500 with a raw TypeError when multipart files were absent. Make image optional and raise BadRequestError so OpenAI-compatible clients get HTTP 400. Fixes #42185 Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
parent
db408f68ae
commit
035dd3e98c
2 changed files with 82 additions and 4 deletions
|
|
@ -965,9 +965,9 @@ def image_edit(
|
|||
|
||||
@client
|
||||
async def aimage_edit(
|
||||
image: FileTypes | list[FileTypes],
|
||||
model: str,
|
||||
prompt: str,
|
||||
image: FileTypes | list[FileTypes] | None = None,
|
||||
model: str | None = None,
|
||||
prompt: str | None = None,
|
||||
mask: str | None = None,
|
||||
n: int | None = None,
|
||||
quality: str | ImageGenerationRequestQuality | None = None,
|
||||
|
|
@ -999,10 +999,24 @@ async def aimage_edit(
|
|||
loop: Final = asyncio.get_event_loop()
|
||||
kwargs["async_call"] = True
|
||||
|
||||
if image is None or (isinstance(image, list) and len(image) == 0):
|
||||
message = "Missing required parameter: 'image'."
|
||||
raise litellm.BadRequestError(
|
||||
message=message,
|
||||
model=model or "unknown",
|
||||
llm_provider=custom_llm_provider or "openai",
|
||||
body={
|
||||
"message": message,
|
||||
"type": "invalid_request_error",
|
||||
"param": "image",
|
||||
"code": "missing_required_parameter",
|
||||
},
|
||||
)
|
||||
|
||||
# get custom llm provider so we can use this for mapping exceptions
|
||||
if custom_llm_provider is None:
|
||||
_, custom_llm_provider, _, _ = litellm.get_llm_provider(
|
||||
model=model, api_base=local_vars.get("base_url", None)
|
||||
model=model or DEFAULT_IMAGE_ENDPOINT_MODEL, api_base=local_vars.get("base_url", None)
|
||||
)
|
||||
|
||||
images: Final = image if isinstance(image, list) else [image]
|
||||
|
|
|
|||
64
tests/test_litellm/images/test_aimage_edit_missing_image.py
Normal file
64
tests/test_litellm/images/test_aimage_edit_missing_image.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
"""Regression tests for https://github.com/BerriAI/litellm/issues/42185
|
||||
|
||||
POST /v1/images/edits without a multipart `image` used to TypeError inside
|
||||
aimage_edit (required positional arg) and surface as HTTP 500. A missing client
|
||||
field must be BadRequestError 400.
|
||||
"""
|
||||
|
||||
from collections.abc import Mapping
|
||||
|
||||
import pytest
|
||||
|
||||
import litellm
|
||||
from litellm.images.main import aimage_edit
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"kwargs",
|
||||
[
|
||||
{"model": "openai/gpt-image-1", "prompt": "add a hat"},
|
||||
{"model": "openai/gpt-image-1", "prompt": "add a hat", "image": None},
|
||||
{"model": "openai/gpt-image-1", "prompt": "add a hat", "image": []},
|
||||
],
|
||||
ids=["omitted", "none", "empty_list"],
|
||||
)
|
||||
async def test_aimage_edit_missing_image_raises_bad_request(kwargs: Mapping[str, object]) -> None:
|
||||
with pytest.raises(litellm.BadRequestError) as exc_info:
|
||||
await litellm.aimage_edit(**kwargs)
|
||||
|
||||
err = exc_info.value
|
||||
message = str(err)
|
||||
assert err.status_code == 400
|
||||
assert "Missing required parameter: 'image'" in message
|
||||
assert "positional argument" not in message
|
||||
assert "TypeError" not in message
|
||||
assert getattr(err, "param", None) == "image"
|
||||
assert err.model == "openai/gpt-image-1"
|
||||
assert err.llm_provider == "openai"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_aimage_edit_direct_import_missing_image_raises_bad_request() -> None:
|
||||
with pytest.raises(litellm.BadRequestError) as exc_info:
|
||||
await aimage_edit(model="gpt-image-1", prompt="add a hat")
|
||||
|
||||
err = exc_info.value
|
||||
assert err.status_code == 400
|
||||
assert "Missing required parameter: 'image'" in str(err)
|
||||
assert "positional argument" not in str(err)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_aimage_edit_missing_image_keeps_custom_llm_provider() -> None:
|
||||
with pytest.raises(litellm.BadRequestError) as exc_info:
|
||||
await litellm.aimage_edit(
|
||||
model="gpt-image-1",
|
||||
prompt="add a hat",
|
||||
custom_llm_provider="azure",
|
||||
)
|
||||
|
||||
err = exc_info.value
|
||||
assert err.status_code == 400
|
||||
assert err.llm_provider == "azure"
|
||||
assert err.model == "gpt-image-1"
|
||||
Loading…
Add table
Reference in a new issue