From 03ac9a79de76775d8622fdf93c06c3f0b53d0415 Mon Sep 17 00:00:00 2001 From: Dayuan Jiang <34411969+DayuanJiang@users.noreply.github.com> Date: Wed, 31 Dec 2025 12:20:09 +0900 Subject: [PATCH] fix: detect models that don't support image input and return clear error (#474) Some models (Kimi K2, DeepSeek, Qwen text models) don't support image/vision input. The AI SDK silently drops unsupported image parts, causing confusing responses where the model acts as if no image was uploaded. Added supportsImageInput() function to detect unsupported models by name, and return a 400 error with clear guidance when users try to upload images to these models. Closes #469 --- app/api/chat/route.ts | 17 ++++++++++++++++- lib/ai-providers.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index c8fb0f0..55dbbde 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -12,7 +12,11 @@ import fs from "fs/promises" import { jsonrepair } from "jsonrepair" import path from "path" import { z } from "zod" -import { getAIModel, supportsPromptCaching } from "@/lib/ai-providers" +import { + getAIModel, + supportsImageInput, + supportsPromptCaching, +} from "@/lib/ai-providers" import { findCachedResponse } from "@/lib/cached-responses" import { checkAndIncrementRequest, @@ -295,6 +299,17 @@ async function handleChatRequest(req: Request): Promise { lastUserMessage?.parts?.filter((part: any) => part.type === "file") || [] + // Check if user is sending images to a model that doesn't support them + // AI SDK silently drops unsupported parts, so we need to catch this early + if (fileParts.length > 0 && !supportsImageInput(modelId)) { + return Response.json( + { + error: `The model "${modelId}" does not support image input. Please use a vision-capable model (e.g., GPT-4o, Claude, Gemini) or remove the image.`, + }, + { status: 400 }, + ) + } + // User input only - XML is now in a separate cached system message const formattedUserInput = `User input: """md diff --git a/lib/ai-providers.ts b/lib/ai-providers.ts index 2ef585b..b482143 100644 --- a/lib/ai-providers.ts +++ b/lib/ai-providers.ts @@ -906,3 +906,34 @@ export function supportsPromptCaching(modelId: string): boolean { modelId.startsWith("eu.anthropic") ) } + +/** + * Check if a model supports image/vision input. + * Some models silently drop image parts without error (AI SDK warning only). + */ +export function supportsImageInput(modelId: string): boolean { + const lowerModelId = modelId.toLowerCase() + + // Helper to check if model has vision capability indicator + const hasVisionIndicator = + lowerModelId.includes("vision") || lowerModelId.includes("vl") + + // Models that DON'T support image/vision input (unless vision variant) + // Kimi K2 models don't support images + if (lowerModelId.includes("kimi") && !hasVisionIndicator) { + return false + } + + // DeepSeek text models (not vision variants) + if (lowerModelId.includes("deepseek") && !hasVisionIndicator) { + return false + } + + // Qwen text models (not vision variants like qwen-vl) + if (lowerModelId.includes("qwen") && !hasVisionIndicator) { + return false + } + + // Default: assume model supports images + return true +}