crewAIInc/crewAI · error · ValueError
action='chmod' requires at least one of 'mode', 'owner', or
Error message
action='chmod' requires at least one of 'mode', 'owner', or 'group'.
What it means
DaytonaFileToolSchema._validate_action_args enforces that action='chmod' changes something: at least one of mode (permissions string like '0755'), owner, or group must be provided. With none set the validator raises ValueError, since a chmod that alters nothing is almost certainly a caller mistake.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py:203
@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":
if not self.paths:
raise ValueError(
"action='replace' requires 'paths' (list of file paths)."
)
if not self.pattern:
raise ValueError("action='replace' requires 'pattern'.")
if self.replacement is None:
raise ValueError("action='replace' requires 'replacement'.")
return self
class DaytonaFileTool(DaytonaBaseTool):
"""Read, write, and manage files inside a Daytona sandbox.
Notes:View on GitHub (pinned to 754d7323be)
Solutions
- Provide at least one change target: tool.run(action='chmod', path='/workspace/script.sh', mode='0755').
- To change ownership instead: pass owner='user' and/or group='group'.
- Verify field names: it is 'mode', 'owner', 'group' — not 'permissions'.
Example fix
# before tool.run(action="chmod", path="/workspace/script.sh") # ValueError # after tool.run(action="chmod", path="/workspace/script.sh", mode="0755")
Defensive patterns
Strategy: validation
Validate before calling
def validate_chmod(path: str | None, mode: str | None, owner: str | None, group: str | None) -> None:
if not path:
raise ValueError("chmod requires path")
if not (mode or owner or group):
raise ValueError("chmod requires mode and/or owner and/or group")
validate_chmod(path, mode, owner, group) Try / catch
try:
tool.run(action="chmod", path=p, mode=m)
except ValidationError as e:
if "'mode', 'owner', or 'group'" in str(e):
tool.run(action="chmod", path=p, mode="0644")
else:
raise Prevention
- Default the mode yourself (e.g. '0644') when callers do not choose one.
- Use the exact field names mode/owner/group.
- Do not confuse chmod with mkdir-with-mode.
When it happens
Trigger: Calling DaytonaFileTool with action='chmod' and only a path (no mode/owner/group); passing the permission into a misnamed field; intending 'mkdir with mode' (a different action) instead of chmod.
Common situations: Agent omits the permission argument; caller uses 'permissions' or 'perm' as the field name instead of 'mode'; confusion between action='mkdir' (accepts mode) and action='chmod'.
Related errors
- action={self.action!r} requires 'path'.
- action='append' requires 'content'. Pass the chunk to append
- action='move' requires 'destination'.
- action='find' requires 'pattern' (text to search for inside
- action='search' requires 'pattern' (glob, e.g. '*.py').
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/4c64d654ab5b5899.
Report an issue: GitHub.