crewAIInc/crewAI · error · ValueError

action='write' requires 'path'

Error message

action='write' requires 'path'

What it means

DaytonaFileTool._run's defensive check for action='write': if path is None it raises ValueError before calling self._write(sandbox, path, content or ""). Like the other _run-level checks it is a backstop behind the Pydantic schema validator and normally only fires when _run is called directly without schema validation. Note that content defaults to '' if omitted — only path is mandatory here.

Source

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

        binary: bool = False,
        recursive: bool = False,
        mode: str | None = None,
        destination: str | None = None,
        pattern: str | None = None,
        replacement: str | None = None,
        paths: list[str] | None = None,
        owner: str | None = None,
        group: str | None = None,
    ) -> Any:
        sandbox, should_delete = self._acquire_sandbox()
        try:
            if action == "read":
                if path is None:
                    raise ValueError("action='read' requires 'path'")
                return self._read(sandbox, path, binary=binary)
            if action == "write":
                if path is None:
                    raise ValueError("action='write' requires 'path'")
                return self._write(sandbox, path, content or "", binary=binary)
            if action == "append":
                if path is None:
                    raise ValueError("action='append' requires 'path'")
                return self._append(sandbox, path, content or "", binary=binary)
            if action == "list":
                if path is None:
                    raise ValueError("action='list' requires 'path'")
                return self._list(sandbox, path)
            if action == "delete":
                if path is None:
                    raise ValueError("action='delete' requires 'path'")
                sandbox.fs.delete_file(path, recursive=recursive)
                return {"status": "deleted", "path": path}
            if action == "mkdir":
                if path is None:
                    raise ValueError("action='mkdir' requires 'path'")
                mkdir_mode = mode or "0755"

View on GitHub (pinned to 754d7323be)

Solutions

  1. Use the validated public path: tool.run(action='write', path='/workspace/out.txt', content='data').
  2. If _run must be called directly, guarantee path is a non-None string.
  3. Build the kwargs from DaytonaFileToolSchema so validation runs.

Example fix

# before
tool._run(action="write", path=None, content="hello")  # ValueError

# after
tool.run(action="write", path="/workspace/out.txt", content="hello")
Defensive patterns

Strategy: validation

Validate before calling

def validated_write_call(tool, path: str | None, content: str) -> Any:
    if path is None:
        raise ValueError("action='write' requires an explicit path")
    return tool.run(action="write", path=path, content=content)

Try / catch

try:
    res = tool.run(action="write", path=p, content=c)
except ValueError as e:
    if "requires 'path'" in str(e):
        p = default_output_path()
        res = tool.run(action="write", path=p, content=c)
    else:
        raise

Prevention

When it happens

Trigger: Directly invoking tool._run(action='write', path=None, content='data'); test harness or custom integration bypassing the input schema; argument dict built with .get('path') returning None.

Common situations: Programmatic calls to the private method; tests exercising _run; misconfigured tool wrappers.

Related errors


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