{"record":{"id":"4721ce5d1216df81","repo":"BerriAI/litellm","slug":"error-unsupported-image-format-format-img-type","errorCode":null,"errorMessage":"Error: Unsupported image format. Format={_img_type}. Supported types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']","messagePattern":"Error: Unsupported image format\\. Format=(.+?)\\. Supported types = \\['image/jpeg', 'image/png', 'image/gif', 'image/webp'\\]","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/prompt_templates/image_handling.py","lineNumber":63,"sourceCode":"            raise litellm.ImageFetchError(\n                f\"Error: Image size ({size_mb:.2f}MB) exceeds maximum allowed size ({MAX_IMAGE_URL_DOWNLOAD_SIZE_MB}MB). url={url}\"\n            )\n        image_bytes.extend(chunk)\n\n    base64_image: Final = base64.b64encode(image_bytes).decode(\"utf-8\")\n\n    image_type: Final = response.headers.get(\"Content-Type\")\n    if image_type is None:\n        img_type = url.split(\".\")[-1].lower()\n        _img_type: Final = {\n            \"jpg\": \"image/jpeg\",\n            \"jpeg\": \"image/jpeg\",\n            \"png\": \"image/png\",\n            \"gif\": \"image/gif\",\n            \"webp\": \"image/webp\",\n        }.get(img_type)\n        if _img_type is None:\n            raise Exception(\n                f\"Error: Unsupported image format. Format={_img_type}. Supported types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']\"\n            )\n        img_type = _img_type\n    else:\n        img_type = image_type\n\n    result: Final = f\"data:{img_type};base64,{base64_image}\"\n    in_memory_cache.set_cache(url, result)\n    return result\n\n\nasync def async_convert_url_to_base64(url: str) -> str:\n    if url.startswith(\"data:\") and \";base64,\" in url:\n        return url\n\n    # If MAX_IMAGE_URL_DOWNLOAD_SIZE_MB is 0, block all image downloads\n    if MAX_IMAGE_URL_DOWNLOAD_SIZE_MB == 0:\n        raise litellm.ImageFetchError(","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/prompt_templates/image_handling.py#L45-L81","documentation":"Raised in convert_url_to_base64 when the image HTTP response has no Content-Type header and the URL's file extension is not one of jpg/jpeg/png/gif/webp. The extension is mapped to a MIME type via a fixed dict; unknown or missing extensions raise. Note the message has a formatting bug: it interpolates _img_type which is always None at that point.","triggerScenarios":"Fetching an image URL like https://host/img.svg, .avif, .bmp, a CDN URL with no extension, or an extension hidden behind a query string (?w=800), when the server also omits Content-Type.","commonSituations":"Signed CDN URLs (extension-less or with query params); WebP/AVIF variants the map doesn't cover; presigned S3 URLs stripped of extension; SVG images which are unsupported regardless.","solutions":["Use an image host that returns a proper Content-Type header — the fallback map is then skipped.","Serve the image from an extension-bearing URL (.png/.jpg/.jpeg/.gif/.webp) without a query suffix.","Convert unsupported formats (svg/avif/bmp) to png/jpeg before passing the URL.","Alternatively download and pass the image as a base64 data URI to bypass URL sniffing."],"exampleFix":"# before\n{\"type\": \"image_url\", \"image_url\": {\"url\": \"https://cdn.example.com/avatar?size=512\"}}\n# after\n{\"type\": \"image_url\", \"image_url\": {\"url\": \"https://cdn.example.com/avatar.png\"}}","handlingStrategy":"validation","validationCode":"SUPPORTED = {\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\"}\n\ndef image_url_is_safe(url: str) -> bool:\n    path = urlparse(url).path\n    ext = path.rsplit(\".\", 1)[-1].lower() if \".\" in path else \"\"\n    return ext in SUPPORTED or url.startswith(\"data:image/\")","typeGuard":"def is_probably_supported_image(url: str) -> bool:\n    if url.startswith(\"data:\"):\n        return True\n    ext = urlparse(url).path.rsplit(\".\", 1)[-1].lower()\n    return ext in {\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\"}","tryCatchPattern":"try:\n    resp = litellm.completion(model=..., messages=msgs)\nexcept Exception as e:\n    if \"Unsupported image format\" in str(e):\n        msgs = inline_image_as_data_uri(msgs)  # download + base64 locally\n        resp = litellm.completion(model=..., messages=msgs)","preventionTips":["Prefer data URIs you construct yourself over opaque CDN URLs.","Strip query strings before guessing extensions, or host images with correct Content-Type headers.","Convert svg/avif/bmp to png or jpeg upstream."],"tags":["image","url","mime-type","multimodal"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}