Skip to content

Commit 0509d8a

Browse files
furionwclaude
andcommitted
fix(multimodal): reject any malformed CustomEncoder image item
image_urls is image_items filtered to dicts with a 'Url' key, so the old `image_items and not image_urls` check only fired when ALL items were malformed — a mixed list (some 'Url', some 'Decoded'/malformed) slipped through and was encoded with the bad items silently dropped. Compare lengths instead: reject the request if any item lacks a usable 'Url'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 76a7e4a commit 0509d8a

1 file changed

Lines changed: 9 additions & 8 deletions

File tree

components/src/dynamo/vllm/handlers.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3400,20 +3400,21 @@ async def _assemble_custom_encoder_prompt(
34003400
for item in image_items
34013401
if isinstance(item, dict) and "Url" in item
34023402
]
3403-
if image_items and not image_urls:
3404-
# Image data is present but no usable URL could be extracted.
3403+
if len(image_urls) != len(image_items):
3404+
# At least one image item was malformed — not a dict with a 'Url'
3405+
# key (e.g. a pre-'Decoded' variant the CustomEncoder can't take).
3406+
# Reject the whole request instead of silently dropping images.
34053407
msg = (
3406-
"CustomEncoder received image multimodal data but could not "
3407-
f"extract any URLs from {len(image_items)} item(s); each item "
3408-
"must be a dict with a 'Url' key"
3408+
"CustomEncoder received image multimodal data but only "
3409+
f"{len(image_urls)} of {len(image_items)} item(s) had a usable "
3410+
"'Url'; each item must be a dict with a 'Url' key"
34093411
)
34103412
logger.error("Request %s: %s", request_id, msg)
34113413
return None, None, {"finish_reason": f"error: {msg}", "token_ids": []}
34123414

34133415
if not image_urls:
3414-
# No usable image URLs, and non-image modalities were already
3415-
# rejected above, so there is nothing for the CustomEncoder to
3416-
# assemble and nothing to extract → text-only request.
3416+
# No image items at all — and non-image modalities were already
3417+
# rejected above — so there is nothing to assemble → text-only.
34173418
return None, None, None
34183419

34193420
token_ids: list[int] = request.get("token_ids") or []

0 commit comments

Comments
 (0)