fix(execution): recognize undecodable-image errors across providers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-10-12 16:17:56 +00:00
parent bf421929ea
commit 21fac52785
2 changed files with 40 additions and 5 deletions

View file

@ -57,9 +57,10 @@ logger = logging.getLogger(__name__)
StreamEventSink = Callable[[str, Any], None]
_INPUT_REJECTION_CODES = frozenset({400, 404, 422})
# Replies meaning "this model takes no images", not image errors in general: a
# context overflow that counts "image/vision expansion" must not match.
_INPUT_REJECTION_CODES = frozenset({400, 404, 415, 422})
# Replies meaning "this model takes no images" or "this image is not a decodable
# image"; stripping images and retrying fixes both. Not image errors in general:
# a context overflow that counts "image/vision expansion" must not match.
_IMAGE_REJECTION = re.compile(
r"no endpoints found that support image input" # OpenRouter
r"|image_url is only supported by certain models" # OpenAI
@ -68,8 +69,15 @@ _IMAGE_REJECTION = re.compile(
r"|doesn't support the image field" # Bedrock Converse
r"|unknown variant `image_url`" # DeepSeek, e.g. via Vercel AI Gateway
r"|'[^']*image[^']*' functionality not supported" # Vercel AI Gateway (AI SDK), unverified
r"|does not contain a valid JPG, PNG, WebP, or ICO image" # xAI: URL fetched, not an image
r"|unsupported content-type encountered when downloading image", # xAI
r"|\binvalid_image\b" # xAI error code
r"|does not contain a valid JPG, PNG, WebP, or ICO image" # xAI
r"|unsupported content-type encountered when downloading image" # xAI
r"|does not represent a valid image" # OpenAI
r"|could not process image" # Anthropic, Bedrock
r"|provided image is not valid" # Gemini
r"|could not be loaded as a valid image" # Mistral
r"|url did not return an image" # OpenRouter
r"|not an allowed image type|cannot identify image file", # vLLM/PIL-based hosts
re.IGNORECASE,
)
_MAX_COMPACTIONS_PER_CYCLE = 2

View file

@ -203,6 +203,33 @@ async def test_run_cycle_does_not_retry_permanent_error(
"supported content types are [image/jpeg, image/png, image/webp].",
True,
),
(
400,
"The image data you provided does not represent a valid image. Please check "
"your input and try again with one of the supported image formats.",
True,
),
(400, '{"type":"invalid_request_error","message":"Could not process image"}', True),
(
400,
'{"code":400,"message":"Provided image is not valid.","status":"INVALID_ARGUMENT"}',
True,
),
(
400,
"Image, 'https://example.com/', could not be loaded as a valid image. "
"Allowed formats are JPEG, PNG, WEBP, GIF",
True,
),
(
415,
'{"error":{"message":"URL did not return an image (received text/error content): '
'https://example.com/","code":415}}',
True,
),
(400, "image_url content type is not an allowed image type: text/html", True),
(400, "cannot identify image file <_io.BytesIO object>", True),
(400, '{"error":{"code":"invalid_image_detail"}}', False),
(
400,
"OpenRouterException: Message: This model's maximum context length is 1048576 "