infiniflow/ragflow · error · ValueError

new_name can only be used with a single file

Error message

new_name can only be used with a single file

What it means

ValueError from MoveFileReq.check_operation (api/utils/validation_utils.py:1097). Renaming via new_name is inherently single-object: giving several files one new name is meaningless, so when src_file_ids has more than one entry and new_name is set, Pydantic rejects the request. Move-many and rename-one must be separate calls.

Source

Thrown at api/utils/validation_utils.py:1097

    """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")
    @classmethod
    def validate_page_size(cls, v: int) -> int:

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Drop new_name when moving multiple files (send only src_file_ids + dest_file_id).
  2. Issue one request per file when renaming: src_file_ids=[one_id] with new_name.
  3. Disable the rename field in the UI whenever more than one file is selected.

Example fix

// before
{"src_file_ids": ["f1", "f2"], "dest_file_id": "d1", "new_name": "renamed"}
// after
{"src_file_ids": ["f1", "f2"], "dest_file_id": "d1"}
Defensive patterns

Strategy: validation

Validate before calling

if len(src_file_ids) > 1:
    payload.pop("new_name", None)
if payload.get("new_name") and len(src_file_ids) > 1:
    raise AssertionError("unreachable: new_name must be dropped for multi-file moves")

Type guard

def is_single_file_rename(src: list[str], new_name: str | None) -> bool:
    return new_name is None or len(src) == 1

Try / catch

try:
    req = MoveFileReq(**payload)
except ValidationError as e:
    if "single file" in str(e):
        payload.pop("new_name")
        req = MoveFileReq(**payload)
    else:
        raise

Prevention

When it happens

Trigger: POST to the move/rename endpoint with len(src_file_ids) > 1 AND a non-null new_name in the same payload.

Common situations: UI letting users multi-select then type a name; generic client code that always fills both fields; merging a 'rename' form state into a bulk-move request.

Related errors


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