{"record":{"id":"a9cd6e777fd450fe","repo":"crewAIInc/crewAI","slug":"action-move-requires-path-and-destination","errorCode":null,"errorMessage":"action='move' requires 'path' and 'destination'","messagePattern":"action='move' requires 'path' and 'destination'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py","lineNumber":292,"sourceCode":"                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:\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 \"","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/daytona_sandbox_tool/daytona_file_tool.py#L274-L310","documentation":"action='move' in DaytonaFileTool._run needs BOTH 'path' (source) and 'destination' (target); if either is None it raises ValueError before calling sandbox.fs.move_files. The asymmetry with other actions (which need only path) is enforced with a single combined check. This is a client-side validation failure only.","triggerScenarios":"Calling _run(action='move', path='/a.txt') without destination, or _run(action='move', destination='/b.txt') without path; agents that rename by supplying only the new name.","commonSituations":"Agents treating move like rename (single argument); users assuming the tool infers the destination directory; kwargs sent as positionally ordered JSON that the schema does not accept.","solutions":["Supply both arguments: _run(action='move', path='/workspace/a.txt', destination='/archive/a.txt').","Pre-validate: for action='move' require both keys present and non-None.","Update the agent's tool instructions to state move takes exactly two required arguments."],"exampleFix":"# before\nfile_tool._run(action='move', path='/tmp/draft.md')\n\n# after\nfile_tool._run(action='move', path='/tmp/draft.md', destination='/docs/final.md')","handlingStrategy":"validation","validationCode":"def move_file(file_tool, path: str | None, destination: str | None):\n    if not path or not destination:\n        raise ValueError(\"action='move' requires both 'path' and 'destination'\")\n    return file_tool._run(action='move', path=path, destination=destination)","typeGuard":null,"tryCatchPattern":"try:\n    file_tool._run(action='move', path=p, destination=d)\nexcept ValueError as e:\n    if 'path' in str(e) and 'destination' in str(e):\n        d = d or default_archive_dir(p)  # fill a sensible default and retry once\n        file_tool._run(action='move', path=p, destination=d)\n    else:\n        raise","preventionTips":["Model move as a two-field dataclass/TypedDict so both are enforced statically.","Generate destination from path with an explicit function instead of relying on the agent.","Assert both keys non-None in a pre-dispatch validator."],"tags":["daytona","argument-validation","file-tool","move"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}