{"record":{"id":"561bc70368952f1b","repo":"crewAIInc/crewAI","slug":"action-append-requires-path","errorCode":null,"errorMessage":"action='append' requires 'path'","messagePattern":"action='append' requires 'path'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py","lineNumber":265,"sourceCode":"        pattern: str | None = None,\n        replacement: str | None = None,\n        paths: list[str] | None = None,\n        owner: str | None = None,\n        group: str | None = None,\n    ) -> Any:\n        sandbox, should_delete = self._acquire_sandbox()\n        try:\n            if action == \"read\":\n                if path is None:\n                    raise ValueError(\"action='read' requires 'path'\")\n                return self._read(sandbox, path, binary=binary)\n            if action == \"write\":\n                if path is None:\n                    raise ValueError(\"action='write' requires 'path'\")\n                return self._write(sandbox, path, content or \"\", binary=binary)\n            if action == \"append\":\n                if path is None:\n                    raise ValueError(\"action='append' requires 'path'\")\n                return self._append(sandbox, path, content or \"\", binary=binary)\n            if action == \"list\":\n                if path is None:\n                    raise ValueError(\"action='list' requires 'path'\")\n                return self._list(sandbox, path)\n            if action == \"delete\":\n                if path is None:\n                    raise ValueError(\"action='delete' requires 'path'\")\n                sandbox.fs.delete_file(path, recursive=recursive)\n                return {\"status\": \"deleted\", \"path\": path}\n            if action == \"mkdir\":\n                if path is None:\n                    raise ValueError(\"action='mkdir' requires 'path'\")\n                mkdir_mode = mode or \"0755\"\n                sandbox.fs.create_folder(path, mkdir_mode)\n                return {\"status\": \"created\", \"path\": path, \"mode\": mkdir_mode}\n            if action == \"info\":\n                if path is None:","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py#L247-L283","documentation":"DaytonaFileTool._run's defensive check for action='append': path must not be None before self._append(sandbox, path, content or \"\") runs. The schema validator already requires both path and content for append, so this branch is effectively dead code unless _run is invoked directly, skipping Pydantic validation.","triggerScenarios":"Direct tool._run(action='append', path=None, ...) calls; test code or custom integrations that bypass the schema; kwargs assembled with a missing 'path' key.","commonSituations":"Unit tests calling the private method; wrapper code invoking _run for speed; partially-built argument dictionaries.","solutions":["Route through the public API: tool.run(action='append', path='/workspace/log.txt', content='line').","When calling _run directly, always supply path (and content).","Validate arguments against DaytonaFileToolSchema first."],"exampleFix":"# before\ntool._run(action=\"append\", path=None, content=\"x\")  # ValueError\n\n# after\ntool.run(action=\"append\", path=\"/workspace/log.txt\", content=\"x\")","handlingStrategy":"validation","validationCode":"def validated_append_call(tool, path: str | None, content: str | None) -> Any:\n    if path is None or content is None:\n        raise ValueError(\"append requires both path and content\")\n    return tool.run(action=\"append\", path=path, content=content)","typeGuard":null,"tryCatchPattern":"try:\n    res = tool.run(action=\"append\", path=p, content=c)\nexcept ValueError as e:\n    if \"requires 'path'\" in str(e):\n        raise ValueError(\"append target missing; cannot infer safely\") from e\n    raise","preventionTips":["Always pair (path, content) for append at the call site.","Use run(), not _run(), to keep schema validation in the loop.","Validate agent-generated append calls before dispatch."],"tags":["daytona","filesystem","validation","internal-api"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}