{"record":{"id":"123acb15fdaa5c13","repo":"infiniflow/ragflow","slug":"database-error-file-retrieval","errorCode":null,"errorMessage":"Database error (File retrieval)!","messagePattern":"Database error \\(File retrieval\\)!","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"api/db/services/file_service.py","lineNumber":171,"sourceCode":"        kbs_info_list = []\n        for kb in list(kbs.dicts()):\n            kbs_info_list.append({\"kb_id\": kb[\"id\"], \"kb_name\": kb[\"name\"], \"document_id\": kb[\"document_id\"]})\n        return kbs_info_list\n\n    @classmethod\n    @DB.connection_context()\n    def get_by_pf_id_name(cls, id, name):\n        # Get file by parent folder ID and name\n        # Args:\n        #     id: Parent folder ID\n        #     name: File name\n        # Returns:\n        #     File object or None if not found\n        file = cls.model.select().where((cls.model.parent_id == id) & (cls.model.name == name))\n        if file.count():\n            e, file = cls.get_by_id(file[0].id)\n            if not e:\n                raise RuntimeError(\"Database error (File retrieval)!\")\n            return file\n        return None\n\n    @classmethod\n    @DB.connection_context()\n    def get_id_list_by_id(cls, id, name, count, res):\n        # Recursively get list of file IDs by traversing folder structure\n        # Args:\n        #     id: Starting folder ID\n        #     name: List of folder names to traverse\n        #     count: Current depth in traversal\n        #     res: List to store results\n        # Returns:\n        #     List of file IDs\n        if count < len(name):\n            file = cls.get_by_pf_id_name(id, name[count])\n            if file:\n                res.append(file.id)","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/db/services/file_service.py#L153-L189","documentation":"RuntimeError from FileService.get_by_pf_id_name when a file row matched by (parent_id, name) but the follow-up get_by_id on its id returns not-found. It signals an inconsistent read — the row existed for the SELECT then vanished (or get_by_id's filter differs), so the method refuses to return a half-resolved file.","triggerScenarios":"Folder listing/upload-name check racing a delete: select finds the row, deletion commits, get_by_id misses. Also possible when the matched row is filtered out by get_by_id's conditions.","commonSituations":"Concurrent uploads and deletes in the same folder (two clients); duplicated name check colliding with cleanup jobs; rare in single-user flows.","solutions":["Retry the operation once after re-querying — this is a transient race in most cases.","Avoid deleting and reading the same folder path concurrently; serialize folder mutations per user.","If persistent, inspect the matched row (id, flags) to see why get_by_id rejects it."],"exampleFix":"# before: single attempt\nf = FileService.get_by_pf_id_name(folder_id, name)\n# after: tolerate the race\nfor _ in range(2):\n    try:\n        f = FileService.get_by_pf_id_name(folder_id, name); break\n    except RuntimeError:\n        continue","handlingStrategy":"retry","validationCode":"row = FileService.model.select().where(FileService.model.parent_id == id, FileService.model.name == name)\nif not row.count():\n    return None  # no conflict — nothing to defend against yet","typeGuard":null,"tryCatchPattern":"for attempt in range(2):\n    try:\n        return FileService.get_by_pf_id_name(id, name)\n    except RuntimeError as e:\n        if 'File retrieval' not in str(e) or attempt == 1:\n            raise\n        continue  # row vanished mid-read; re-select","preventionTips":["Serialize folder mutations per folder (lock or single-writer queue) in multi-client apps.","Treat this as a transient race first; escalate only when it repeats."],"tags":["database","race-condition","file-service","folder"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}