infiniflow/ragflow · error · ValueError

At least one of dest_file_id or new_name must be provided

Error message

At least one of dest_file_id or new_name must be provided

What it means

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.

Source

Thrown at api/utils/validation_utils.py:1095

class DeleteFileReq(Base):
    """Request model for deleting files."""

    ids: Annotated[list[str], Field(min_length=1)]


class MoveFileReq(Base):
    """Request model for moving or renaming files."""

    src_file_ids: Annotated[list[str], Field(min_length=1)]
    dest_file_id: Annotated[str | None, Field(default=None)]
    new_name: Annotated[str | None, StringConstraints(strip_whitespace=True, min_length=1, max_length=255), Field(default=None)]

    @model_validator(mode="after")
    def check_operation(self):
        """Require either a destination folder or a new file name."""
        if not self.dest_file_id and not self.new_name:
            raise ValueError("At least one of dest_file_id or new_name must be provided")
        if self.new_name and len(self.src_file_ids) > 1:
            raise ValueError("new_name can only be used with a single file")
        return self


class ListFileReq(BaseModel):
    """Request model for listing files."""

    model_config = ConfigDict(extra="forbid")

    parent_id: Annotated[str | None, Field(default=None)]
    keywords: Annotated[str, Field(default="")]
    page: Annotated[int, Field(default=1, ge=1)]
    page_size: Annotated[int, Field(default=15, ge=1)]
    orderby: Annotated[str, Field(default="create_time")]
    desc: Annotated[bool, Field(default=True)]

    @field_validator("page_size")

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Include dest_file_id (the target folder id) when moving files.
  2. Include new_name (1-255 chars after trimming) when renaming a single file.
  3. If moving to root, send the actual root folder id rather than an empty string.
  4. Trim user input before assigning it to new_name; all-whitespace names are treated as missing.

Example fix

// before
{"src_file_ids": ["f1"], "dest_file_id": "", "new_name": null}
// after
{"src_file_ids": ["f1"], "dest_file_id": "<root-or-folder-id>"}
Defensive patterns

Strategy: validation

Validate before calling

if not payload.get("dest_file_id") and not payload.get("new_name", "").strip():
    raise ValueError("move/rename requires dest_file_id or a non-empty new_name")

Type guard

def is_valid_move_request(src: list[str], dest: str | None, new_name: str | None) -> bool:
    return bool(src) and (bool(dest) or bool(new_name and new_name.strip()))

Try / catch

try:
    req = MoveFileReq(**payload)
except ValidationError as e:
    if "At least one of dest_file_id or new_name" in str(e):
        # surface to the UI: pick a destination or type a name
        ...
    raise

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/ba4c9c78f6cdc6e9. Report an issue: GitHub.