From 4ef0453cc9e6d43e5d8fdc902aa5ec8b3b4a2970 Mon Sep 17 00:00:00 2001 From: Roland Tannous Date: Thu, 16 Apr 2026 21:09:02 +0400 Subject: [PATCH] fix(studio): reject images in OpenAI tool passthrough for text-only GGUFs The new tool passthrough branch runs before _extract_content_parts, skipping the existing not is_vision guard. Requests combining tools with an image on a text-only tool-capable GGUF were forwarded to llama-server, producing opaque upstream errors instead of the pre-existing clear 400. Restore the guard inline at the dispatch point, checking both legacy image_base64 and inline image_url parts. --- studio/backend/routes/inference.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/studio/backend/routes/inference.py b/studio/backend/routes/inference.py index dc94b2fa84..96b9f827c0 100644 --- a/studio/backend/routes/inference.py +++ b/studio/backend/routes/inference.py @@ -1147,6 +1147,23 @@ async def openai_chat_completions( and not payload.enable_tools and ((payload.tools and len(payload.tools) > 0) or _has_tool_messages) ): + # Preserve the vision guard that would otherwise run in the + # non-passthrough path below: text-only tool-capable GGUFs + # should return a clear 400 here rather than forwarding the + # image to llama-server and surfacing an opaque upstream error. + if not llama_backend.is_vision and ( + payload.image_base64 + or any( + isinstance(m.content, list) + and any(isinstance(p, ImageContentPart) for p in m.content) + for m in payload.messages + ) + ): + raise HTTPException( + status_code = 400, + detail = "Image provided but current GGUF model does not support vision.", + ) + cancel_event = threading.Event() completion_id = f"chatcmpl-{uuid.uuid4().hex[:12]}" if payload.stream: