crewAIInc/crewAI · error · ValueError
Unsupported image format. Supported formats: {valid_extensio
Error message
Unsupported image format. Supported formats: {valid_extensions} What it means
VisionTool's image_path_url validator enforces a whitelist of image extensions {.jpg, .jpeg, .png, .gif, .webp} for local files. Any other suffix (checked case-insensitively) raises ValueError listing the supported formats, because the underlying vision model only accepts those MIME types.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/vision_tool/vision_tool.py:30
class ImagePromptSchema(BaseModel):
"""Input for Vision Tool."""
image_path_url: str = "The image path or URL."
@field_validator("image_path_url")
@classmethod
def validate_image_path_url(cls, v: str) -> str:
if v.startswith("http"):
return v
path = Path(v)
if not path.exists():
raise ValueError(f"Image file does not exist: {v}")
valid_extensions = {".jpg", ".jpeg", ".png", ".gif", ".webp"}
if path.suffix.lower() not in valid_extensions:
raise ValueError(
f"Unsupported image format. Supported formats: {valid_extensions}"
)
return v
class VisionTool(BaseTool):
"""Tool for analyzing images using vision models.
Args:
llm: Optional LLM instance to use
model: Model identifier to use if no LLM is provided
"""
name: str = "Vision Tool"
description: str = (
"This tool uses OpenAI's Vision API to describe the contents of an image."
)View on GitHub (pinned to 754d7323be)
Solutions
- Convert the image to a supported format first (e.g., with PIL: img.convert('RGB').save(p, 'PNG')).
- Rename/re-save files with a supported extension after a real conversion - do not just rename, the bytes must match.
- For HEIC/TIFF sources, add pillow-heif / ImageMagick conversion in your upload pipeline.
Example fix
# before
VisionTool().run(image_path_url='/tmp/scan.tiff') # ValueError: unsupported format
# after
from PIL import Image
Image.open('/tmp/scan.tiff').convert('RGB').save('/tmp/scan.png')
VisionTool().run(image_path_url='/tmp/scan.png') Defensive patterns
Strategy: type-guard
Validate before calling
from pathlib import Path
SUPPORTED = {'.jpg', '.jpeg', '.png', '.gif', '.webp'}
def ensure_supported(path: str) -> str:
p = Path(path)
if p.suffix.lower() not in SUPPORTED:
from PIL import Image
new = p.with_suffix('.png')
Image.open(p).convert('RGB').save(new)
return str(new)
return path Type guard
from pathlib import Path
def is_supported_image(v: str) -> bool:
return v.startswith('http') or Path(v).suffix.lower() in {'.jpg', '.jpeg', '.png', '.gif', '.webp'} Try / catch
try:
VisionTool().run(image_path_url=path)
except ValueError as e:
if 'Unsupported image format' in str(e):
path = convert_with_pil(path, target='.png') # real conversion, not rename
VisionTool().run(image_path_url=path)
else:
raise Prevention
- Convert HEIC/TIFF/BMP uploads to PNG/JPEG in your ingestion pipeline.
- Filter candidate images by extension before handing paths to the model.
- Never fix by renaming only - bytes must actually be re-encoded.
When it happens
Trigger: Calling VisionTool.run(image_path_url='/tmp/scan.tiff'), '.bmp', '.heic', '.avif', or a file with no extension; also paths with trailing dots or query-like suffixes that survive Path.suffix parsing.
Common situations: Users feeding TIFF/BMP/HEIC exports from cameras, scanners, or screenshots; macOS HEIC photos; downloaded files whose extension was stripped.
Related errors
- Image file does not exist: {v}
- Missing required input '{name}'{suffix}
- Invalid input '{location}': {error.get('msg')}
- Expected an async readable object with async read() method
- Expected a binary file-like object with read() and seek()
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/55053fcfc0b22fed.
Report an issue: GitHub.