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

  1. Convert the image to a supported format first (e.g., with PIL: img.convert('RGB').save(p, 'PNG')).
  2. Rename/re-save files with a supported extension after a real conversion - do not just rename, the bytes must match.
  3. 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

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


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/55053fcfc0b22fed. Report an issue: GitHub.