{"record":{"id":"e761648463743e00","repo":"crewAIInc/crewAI","slug":"action-search-requires-pattern-glob-e-g","errorCode":null,"errorMessage":"action='search' requires 'pattern' (glob, e.g. '*.py').","messagePattern":"action='search' requires 'pattern' \\(glob, e\\.g\\. '\\*\\.py'\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py","lineNumber":201,"sourceCode":"    )\n\n    @model_validator(mode=\"after\")\n    def _validate_action_args(self) -> DaytonaFileToolSchema:\n        if self.action != \"replace\" and not self.path:\n            raise ValueError(f\"action={self.action!r} requires 'path'.\")\n        if self.action == \"append\" and self.content is None:\n            raise ValueError(\n                \"action='append' requires 'content'. Pass the chunk to append \"\n                \"in the 'content' field.\"\n            )\n        if self.action == \"move\" and not self.destination:\n            raise ValueError(\"action='move' requires 'destination'.\")\n        if self.action == \"find\" and not self.pattern:\n            raise ValueError(\n                \"action='find' requires 'pattern' (text to search for inside files).\"\n            )\n        if self.action == \"search\" and not self.pattern:\n            raise ValueError(\"action='search' requires 'pattern' (glob, e.g. '*.py').\")\n        if self.action == \"chmod\" and not (self.mode or self.owner or self.group):\n            raise ValueError(\n                \"action='chmod' requires at least one of 'mode', 'owner', or 'group'.\"\n            )\n        if self.action == \"replace\":\n            if not self.paths:\n                raise ValueError(\n                    \"action='replace' requires 'paths' (list of file paths).\"\n                )\n            if not self.pattern:\n                raise ValueError(\"action='replace' requires 'pattern'.\")\n            if self.replacement is None:\n                raise ValueError(\"action='replace' requires 'replacement'.\")\n        return self\n\n\nclass DaytonaFileTool(DaytonaBaseTool):\n    \"\"\"Read, write, and manage files inside a Daytona sandbox.","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py#L183-L219","documentation":"DaytonaFileToolSchema._validate_action_args requires action='search' to carry a pattern, where 'search' means glob-style filename search (e.g. '*.py'). A missing or empty pattern raises this ValueError during input validation, before the sandbox filesystem is touched.","triggerScenarios":"Calling DaytonaFileTool with action='search' and a directory path but no pattern; passing the search text in the wrong field; passing a glob into a different argument name.","commonSituations":"Agent confuses search (glob) with find (file contents); caller passes pattern as 'query' or 'glob'; empty pattern from a formatted string that evaluated to ''.","solutions":["Provide a glob: tool.run(action='search', path='/workspace', pattern='*.py').","For content search, switch to action='find' with the literal text as pattern.","Double-check the field name is exactly 'pattern'."],"exampleFix":"# before\ntool.run(action=\"search\", path=\"/workspace\")  # ValueError\n\n# after\ntool.run(action=\"search\", path=\"/workspace\", pattern=\"*.py\")","handlingStrategy":"validation","validationCode":"def validate_search(path: str | None, pattern: str | None) -> None:\n    if not path:\n        raise ValueError(\"search requires path (directory)\")\n    if not pattern:\n        raise ValueError(\"search requires pattern = glob like '*.py'\")\n\nvalidate_search(path, pattern)","typeGuard":null,"tryCatchPattern":"try:\n    tool.run(action=\"search\", path=p, pattern=pat)\nexcept ValidationError as e:\n    if \"glob\" in str(e):\n        pat = \"*\"  # or a more specific glob\n        tool.run(action=\"search\", path=p, pattern=pat)\n    else:\n        raise","preventionTips":["Use action='search' only with glob patterns; use 'find' for text content.","Sanity-check that pattern is a valid glob (non-empty, no NUL) before the call.","Keep a one-line cheat sheet of Daytona file actions in your tool wrapper."],"tags":["daytona","pydantic","validation","input-validation","search"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}