infiniflow/ragflow · error · RuntimeError

Database error (File move)!

Error message

Database error (File move)!

What it means

Raised by FileService.move_file when cls.filter_update on the file rows fails. The update sets parent_id = folder_id for all ids in file_ids; any DB exception during that UPDATE (constraint, lock, invalid folder_id) is logged and re-raised as this RuntimeError.

Source

Thrown at api/db/services/file_service.py:538

            "tenant_id": tenant_id,
            "created_by": tenant_id,
            "name": doc["name"],
            "type": doc["type"],
            "size": doc["size"],
            "location": doc["location"],
            "source_type": FileSource.KNOWLEDGEBASE,
        }
        cls.save(**file)
        File2DocumentService.save(id=get_uuid(), file_id=file["id"], document_id=doc["id"])

    @classmethod
    @DB.connection_context()
    def move_file(cls, file_ids, folder_id):
        try:
            cls.filter_update((cls.model.id << file_ids,), {"parent_id": folder_id})
        except Exception:
            logger.exception("move_file")
            raise RuntimeError("Database error (File move)!")

    @classmethod
    @DB.connection_context()
    def upload_document(self, kb, file_objs, user_id, src="local", parent_path: str | None = None, parser_config_override: dict | None = None):
        root_folder = self.get_root_folder(user_id)
        pf_id = root_folder["id"]
        self.init_knowledgebase_docs(pf_id, user_id)
        kb_root_folder = self.get_kb_folder(user_id)
        kb_folder = self.new_a_file_from_kb(kb.tenant_id, kb.name, kb_root_folder["id"])

        safe_parent_path = sanitize_path(parent_path)

        # Merge parser_config_override with KB parser_config if provided
        base_parser_config = kb.parser_config or {}
        if parser_config_override and isinstance(parser_config_override, dict):
            merged_parser_config = {**base_parser_config, **parser_config_override}
        else:
            merged_parser_config = base_parser_config

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Confirm the target folder exists and belongs to the same tenant before calling move_file.
  2. Check logs for the underlying Peewee error (usually IntegrityError or OperationalError).
  3. Retry the move after the concurrent operation finishes if the log shows a lock wait timeout.
  4. Reduce the batch size of file_ids if the update times out on large lists.

Example fix

# before
FileService.move_file(file_ids, folder_id)

# after
ok, target = FileService.get_by_id(folder_id)
if not ok or target.type != FileType.FOLDER.value:
    return json_error_response('target folder not found', code=404)
FileService.move_file(file_ids, folder_id)
Defensive patterns

Strategy: validation

Validate before calling

ok, target = FileService.get_by_id(folder_id)
if not ok:
    return json_error_response('target folder not found', 404)
FileService.move_file(file_ids, folder_id)

Type guard

def is_valid_move_target(folder_id: str, user_id: str) -> bool:
    q = FileService.model.select().where(
        (FileService.model.id == folder_id)
        & (FileService.model.tenant_id == user_id)
        & (FileService.model.type == FileType.FOLDER.value)
    )
    return q.exists()

Try / catch

try:
    FileService.move_file(file_ids, folder_id)
except RuntimeError as e:
    return json_error_response(f'move failed: {e}', 500)

Prevention

When it happens

Trigger: Calling the file-move API with a target folder_id that does not exist or belongs to another tenant (FK violation), moving a very large id list that times out, or moving files while another transaction holds locks on those rows.

Common situations: Drag-and-drop in the web UI targeting a folder deleted in another session; API callers passing arbitrary folder ids without validation; concurrent moves/uploads on the same files.

Related errors


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