{"record":{"id":"ba4c9c78f6cdc6e9","repo":"infiniflow/ragflow","slug":"at-least-one-of-dest-file-id-or-new-name-must-be-p","errorCode":null,"errorMessage":"At least one of dest_file_id or new_name must be provided","messagePattern":"At least one of dest_file_id or new_name must be provided","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"api/utils/validation_utils.py","lineNumber":1095,"sourceCode":"\nclass DeleteFileReq(Base):\n    \"\"\"Request model for deleting files.\"\"\"\n\n    ids: Annotated[list[str], Field(min_length=1)]\n\n\nclass MoveFileReq(Base):\n    \"\"\"Request model for moving or renaming files.\"\"\"\n\n    src_file_ids: Annotated[list[str], Field(min_length=1)]\n    dest_file_id: Annotated[str | None, Field(default=None)]\n    new_name: Annotated[str | None, StringConstraints(strip_whitespace=True, min_length=1, max_length=255), Field(default=None)]\n\n    @model_validator(mode=\"after\")\n    def check_operation(self):\n        \"\"\"Require either a destination folder or a new file name.\"\"\"\n        if not self.dest_file_id and not self.new_name:\n            raise ValueError(\"At least one of dest_file_id or new_name must be provided\")\n        if self.new_name and len(self.src_file_ids) > 1:\n            raise ValueError(\"new_name can only be used with a single file\")\n        return self\n\n\nclass ListFileReq(BaseModel):\n    \"\"\"Request model for listing files.\"\"\"\n\n    model_config = ConfigDict(extra=\"forbid\")\n\n    parent_id: Annotated[str | None, Field(default=None)]\n    keywords: Annotated[str, Field(default=\"\")]\n    page: Annotated[int, Field(default=1, ge=1)]\n    page_size: Annotated[int, Field(default=15, ge=1)]\n    orderby: Annotated[str, Field(default=\"create_time\")]\n    desc: Annotated[bool, Field(default=True)]\n\n    @field_validator(\"page_size\")","sourceCodeStart":1077,"sourceCodeEnd":1113,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/utils/validation_utils.py#L1077-L1113","documentation":"ValueError from MoveFileReq.check_operation, a model_validator(mode='after') on the file move/rename request model (api/utils/validation_utils.py:1091-1098). The move-files endpoint is a single endpoint for both moving and renaming; Pydantic rejects a payload that supplies neither a destination folder (dest_file_id) nor a new name (new_name), because the operation would be a no-op.","triggerScenarios":"POST to the file move/rename API with only src_file_ids and both dest_file_id and new_name omitted, empty, or None. Also triggered when dest_file_id is an empty string (falsy check) or new_name is only whitespace (StringConstraints strip_whitespace + min_length=1 turns it into None/invalid).","commonSituations":"Front-end firing the move dialog with no target folder selected; sending an empty-string dest_file_id to mean 'root folder'; whitespace-only new_name from an untrimmed input field.","solutions":["Include dest_file_id (the target folder id) when moving files.","Include new_name (1-255 chars after trimming) when renaming a single file.","If moving to root, send the actual root folder id rather than an empty string.","Trim user input before assigning it to new_name; all-whitespace names are treated as missing."],"exampleFix":"// before\n{\"src_file_ids\": [\"f1\"], \"dest_file_id\": \"\", \"new_name\": null}\n// after\n{\"src_file_ids\": [\"f1\"], \"dest_file_id\": \"<root-or-folder-id>\"}","handlingStrategy":"validation","validationCode":"if not payload.get(\"dest_file_id\") and not payload.get(\"new_name\", \"\").strip():\n    raise ValueError(\"move/rename requires dest_file_id or a non-empty new_name\")","typeGuard":"def is_valid_move_request(src: list[str], dest: str | None, new_name: str | None) -> bool:\n    return bool(src) and (bool(dest) or bool(new_name and new_name.strip()))","tryCatchPattern":"try:\n    req = MoveFileReq(**payload)\nexcept ValidationError as e:\n    if \"At least one of dest_file_id or new_name\" in str(e):\n        # surface to the UI: pick a destination or type a name\n        ...\n    raise","preventionTips":["Trim new_name client-side; whitespace-only counts as missing.","Disable the confirm button until destination or new name is chosen.","Use the real root-folder id rather than empty string for root moves."],"tags":["validation","pydantic","file-management","move-rename"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}