crewAIInc/crewAI · error · ValueError

action={self.action!r} requires 'path'.

Error message

action={self.action!r} requires 'path'.

What it means

DaytonaFileToolSchema's Pydantic model_validator(_validate_action_args) enforces per-action required arguments. Every action except 'replace' operates on a single 'path', so when action is anything other than 'replace' and path is missing/falsy, validation fails with this ValueError (surfaced as pydantic.ValidationError). It fires at input-schema construction time, before any sandbox is created.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py:188

        default=None,
        description=(
            "For action='replace': list of absolute file paths in which to "
            "replace 'pattern' with 'replacement'."
        ),
    )
    owner: str | None = Field(
        default=None,
        description="For action='chmod': new file owner (user name).",
    )
    group: str | None = Field(
        default=None,
        description="For action='chmod': new file group.",
    )

    @model_validator(mode="after")
    def _validate_action_args(self) -> DaytonaFileToolSchema:
        if self.action != "replace" and not self.path:
            raise ValueError(f"action={self.action!r} requires 'path'.")
        if self.action == "append" and self.content is None:
            raise ValueError(
                "action='append' requires 'content'. Pass the chunk to append "
                "in the 'content' field."
            )
        if self.action == "move" and not self.destination:
            raise ValueError("action='move' requires 'destination'.")
        if self.action == "find" and not self.pattern:
            raise ValueError(
                "action='find' requires 'pattern' (text to search for inside files)."
            )
        if self.action == "search" and not self.pattern:
            raise ValueError("action='search' requires 'pattern' (glob, e.g. '*.py').")
        if self.action == "chmod" and not (self.mode or self.owner or self.group):
            raise ValueError(
                "action='chmod' requires at least one of 'mode', 'owner', or 'group'."
            )
        if self.action == "replace":

View on GitHub (pinned to 754d7323be)

Solutions

  1. Include a non-empty path for the chosen action, e.g. tool.run(action='read', path='/workspace/main.py').
  2. For bulk find-and-replace across many files, use action='replace' with paths=[...], pattern=..., replacement=... instead of omitting path.
  3. If an LLM drives the tool, make the schema descriptions explicit that path is required for all non-replace actions (the field descriptions already state this).
  4. Log the raw tool arguments before the call to spot omitted fields.

Example fix

# before
tool.run(action="read")  # missing path

# after
tool.run(action="read", path="/workspace/main.py")
Defensive patterns

Strategy: validation

Validate before calling

def validate_file_tool_args(action: str, path: str | None) -> None:
    if action != "replace" and not path:
        raise ValueError(f"action={action!r} requires 'path'")

validate_file_tool_args(action, path)  # before tool.run(...)

Try / catch

from pydantic import ValidationError

try:
    result = tool.run(action=action, path=path)
except ValidationError as e:
    if "requires 'path'" in str(e):
        # ask caller/LLM for the missing path and retry
        path = request_path()
        result = tool.run(action=action, path=path)
    else:
        raise

Prevention

When it happens

Trigger: Invoking DaytonaFileTool with action='read'/'write'/'append'/'list'/'delete'/'mkdir'/'move'/'find'/'search'/'chmod' but no path argument; an LLM emitting a tool call with only action set; path passed as empty string.

Common situations: Agent omits path in tool arguments; caller confuses 'replace' (multi-file, uses paths) with single-file actions and passes paths=[] only; empty-string path from template interpolation.

Related errors


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