{"record":{"id":"84ec7f28ff12521f","repo":"crewAIInc/crewAI","slug":"action-write-requires-path","errorCode":null,"errorMessage":"action='write' requires 'path'","messagePattern":"action='write' 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":261,"sourceCode":"        binary: bool = False,\n        recursive: bool = False,\n        mode: str | None = None,\n        destination: str | None = None,\n        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\"","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py#L243-L279","documentation":"DaytonaFileTool._run's defensive check for action='write': if path is None it raises ValueError before calling self._write(sandbox, path, content or \"\"). Like the other _run-level checks it is a backstop behind the Pydantic schema validator and normally only fires when _run is called directly without schema validation. Note that content defaults to '' if omitted — only path is mandatory here.","triggerScenarios":"Directly invoking tool._run(action='write', path=None, content='data'); test harness or custom integration bypassing the input schema; argument dict built with .get('path') returning None.","commonSituations":"Programmatic calls to the private method; tests exercising _run; misconfigured tool wrappers.","solutions":["Use the validated public path: tool.run(action='write', path='/workspace/out.txt', content='data').","If _run must be called directly, guarantee path is a non-None string.","Build the kwargs from DaytonaFileToolSchema so validation runs."],"exampleFix":"# before\ntool._run(action=\"write\", path=None, content=\"hello\")  # ValueError\n\n# after\ntool.run(action=\"write\", path=\"/workspace/out.txt\", content=\"hello\")","handlingStrategy":"validation","validationCode":"def validated_write_call(tool, path: str | None, content: str) -> Any:\n    if path is None:\n        raise ValueError(\"action='write' requires an explicit path\")\n    return tool.run(action=\"write\", path=path, content=content)","typeGuard":null,"tryCatchPattern":"try:\n    res = tool.run(action=\"write\", path=p, content=c)\nexcept ValueError as e:\n    if \"requires 'path'\" in str(e):\n        p = default_output_path()\n        res = tool.run(action=\"write\", path=p, content=c)\n    else:\n        raise","preventionTips":["Compute the destination path before building tool arguments.","Route calls through run() so schema validation catches omissions early.","Reject LLM tool calls that omit required fields before execution."],"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"}