{"record":{"id":"afcd2b8348a588e3","repo":"crewAIInc/crewAI","slug":"action-search-requires-path-and-pattern","errorCode":null,"errorMessage":"action='search' requires 'path' and 'pattern'","messagePattern":"action='search' requires 'path' and 'pattern'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py","lineNumber":301,"sourceCode":"                if path is None:\n                    raise ValueError(\"action='info' requires 'path'\")\n                return self._info(sandbox, path)\n            if action == \"exists\":\n                if path is None:\n                    raise ValueError(\"action='exists' requires 'path'\")\n                return self._exists(sandbox, path)\n            if action == \"move\":\n                if path is None or destination is None:\n                    raise ValueError(\"action='move' requires 'path' and 'destination'\")\n                sandbox.fs.move_files(path, destination)\n                return {\"status\": \"moved\", \"from\": path, \"to\": destination}\n            if action == \"find\":\n                if path is None or pattern is None:\n                    raise ValueError(\"action='find' requires 'path' and 'pattern'\")\n                return self._find(sandbox, path, pattern)\n            if action == \"search\":\n                if path is None or pattern is None:\n                    raise ValueError(\"action='search' requires 'path' and 'pattern'\")\n                return self._search(sandbox, path, pattern)\n            if action == \"chmod\":\n                if path is None:\n                    raise ValueError(\"action='chmod' requires 'path'\")\n                return self._chmod(sandbox, path, mode=mode, owner=owner, group=group)\n            if action == \"replace\":\n                if paths is None or pattern is None or replacement is None:\n                    raise ValueError(\n                        \"action='replace' requires 'paths', 'pattern', and \"\n                        \"'replacement'\"\n                    )\n                return self._replace(sandbox, paths, pattern, replacement)\n            raise ValueError(f\"Unknown action: {action}\")\n        finally:\n            self._release_sandbox(sandbox, should_delete)\n\n    def _read(self, sandbox: Any, path: str, *, binary: bool) -> dict[str, Any]:\n        data: bytes = sandbox.fs.download_file(path)","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py#L283-L319","documentation":"action='search' in DaytonaFileTool._run requires 'path' (file or directory to scan) and 'pattern' (text/regex to look for); missing either raises ValueError before self._search runs. Unlike 'find' (filename globbing), search inspects file contents, but the validation shape is identical. This is argument validation, not a search failure.","triggerScenarios":"Calling _run(action='search', path='/src') with no pattern; _run(action='search', pattern='TODO') with no path; agents swapping in 'query' or 'regex' as the kwarg name.","commonSituations":"Agents emitting a generic 'query' field instead of 'pattern'; users assuming search defaults to the whole sandbox; mixing up find and search argument expectations.","solutions":["Pass both arguments: _run(action='search', path='/src/app', pattern='API_KEY').","Validate that action='search' calls include path and pattern before invoking the tool.","Clarify in the tool description that pattern here is content text/regex, not a filename glob."],"exampleFix":"# before\nfile_tool._run(action='search', query='API_KEY')\n\n# after\nfile_tool._run(action='search', path='/src/app', pattern='API_KEY')","handlingStrategy":"validation","validationCode":"def search_contents(file_tool, path: str | None, pattern: str | None):\n    if not path or not pattern:\n        raise ValueError(\"action='search' requires 'path' and 'pattern'\")\n    return file_tool._run(action='search', path=path, pattern=pattern)","typeGuard":null,"tryCatchPattern":"try:\n    res = file_tool._run(action='search', path=path, pattern=pattern)\nexcept ValueError as e:\n    if \"action='search'\" in str(e):\n        return {'error': 'missing path or pattern', 'retry_with': {'path': path, 'pattern': pattern}}\n    raise","preventionTips":["Map 'query'-style agent fields to 'pattern' explicitly before dispatch.","Prefer explicit wrappers per action over raw _run calls.","Smoke-test search with a known file and literal pattern."],"tags":["daytona","argument-validation","file-tool","search","regex"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}