crewAIInc/crewAI · error · ValueError

Image file does not exist: {v}

Error message

Image file does not exist: {v}

What it means

VisionTool's Pydantic input schema validates image_path_url. For non-http inputs it converts the string to a Path and checks existence; if the file is not on disk at validation time (i.e., when the tool is invoked), ValueError is raised naming the missing path.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/vision_tool/vision_tool.py:26

from pydantic import BaseModel, Field, PrivateAttr, field_validator

from crewai_tools.security.safe_path import validate_file_path


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
    """

View on GitHub (pinned to 754d7323be)

Solutions

  1. Verify the path before invoking: expand and resolve it with pathlib and check .exists().
  2. Use absolute paths (str(Path(p).resolve())) so CWD differences cannot break resolution.
  3. Mount/copy the image into the container or working directory it runs in.
  4. If the image is remote, pass a full http(s) URL instead, which skips the file check.

Example fix

# before
VisionTool().run(image_path_url='images/cat.jpg')  # CWD mismatch -> ValueError

# after
from pathlib import Path
p = Path('images/cat.jpg').resolve()
assert p.exists(), f'missing image: {p}'
VisionTool().run(image_path_url=str(p))
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def resolve_image(p: str) -> str:
    if p.startswith('http'):
        return p
    path = Path(p).expanduser().resolve()
    if not path.is_file():
        raise FileNotFoundError(f'image not found: {path}')
    return str(path)

# image_path_url = resolve_image(raw_path) before calling VisionTool

Type guard

from pathlib import Path

def is_local_image(v: str) -> bool:
    if v.startswith('http'):
        return False
    p = Path(v).expanduser().resolve()
    return p.is_file() and p.suffix.lower() in {'.jpg', '.jpeg', '.png', '.gif', '.webp'}

Try / catch

try:
    VisionTool().run(image_path_url=path)
except ValueError as e:
    if 'does not exist' in str(e):
        path = str(Path(path).resolve())  # fix CWD-relative path, retry once
        VisionTool().run(image_path_url=path)
    else:
        raise

Prevention

When it happens

Trigger: Calling VisionTool.run(image_path_url='./photo.png') with a relative or absolute path that does not exist relative to the process's current working directory, or a local path while the file lives on another machine/container.

Common situations: Agents hallucinating or typo-ing file paths; relative paths breaking when the worker process has a different CWD (containers, notebooks, cron); files not yet written before the tool call; running in Docker without mounting the image directory.

Related errors


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