crewAIInc/crewAI · error · ValueError

action='replace' requires 'pattern'.

Error message

action='replace' requires 'pattern'.

What it means

Within the action='replace' branch of DaytonaFileToolSchema._validate_action_args, after paths is confirmed present, a non-empty pattern (the text to find) is required. Omitting pattern or passing an empty string raises this ValueError.

Source

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

        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:
      - Most useful with `persistent=True` or an explicit `sandbox_id`. With the
        default ephemeral mode, files disappear when this tool call finishes.
    """

    name: str = "Daytona Sandbox Files"
    description: str = (
        "Perform filesystem operations inside a Daytona sandbox: read, "
        "write, append, list, delete, mkdir, info, exists, move, find "
        "(content grep), search (filename glob), chmod (permissions/owner/"

View on GitHub (pinned to 754d7323be)

Solutions

  1. Pass the text to find: tool.run(action='replace', paths=[...], pattern='old_name', replacement='new_name').
  2. Verify pattern (what to find) vs replacement (what to write) are in the right fields.
  3. Assert pattern is a non-empty string before the call.

Example fix

# before
tool.run(action="replace", paths=["/workspace/a.py"], replacement="bar")  # ValueError

# after
tool.run(action="replace", paths=["/workspace/a.py"], pattern="foo", replacement="bar")
Defensive patterns

Strategy: validation

Validate before calling

def validate_replace_pattern(pattern: str | None) -> str:
    if not pattern:
        raise ValueError("replace requires a non-empty pattern to match")
    return pattern

Try / catch

try:
    tool.run(action="replace", paths=ps, pattern=pat, replacement=rep)
except ValidationError as e:
    if "requires 'pattern'" in str(e):
        raise ValueError("No search term supplied for bulk replace; refusing to run") from e
    raise

Prevention

When it happens

Trigger: Calling DaytonaFileTool with action='replace', paths and replacement set, but pattern missing/empty; caller swapping pattern and replacement arguments.

Common situations: Agent omits the search term; empty pattern from variable interpolation; swapped arguments so pattern receives the new text and the check on the real pattern is bypassed by a similar-looking value.

Related errors


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