{"record":{"id":"98b4e435a9955ea5","repo":"infiniflow/ragflow","slug":"document-not-found","errorCode":null,"errorMessage":"document not found","messagePattern":"document not found","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"warning","filePath":"api/db/services/file_service.py","lineNumber":715,"sourceCode":"\n    @staticmethod\n    def put_blob(user_id, location, blob):\n        bname = f\"{user_id}-downloads\"\n        return settings.STORAGE_IMPL.put(bname, location, blob)\n\n    @classmethod\n    @DB.connection_context()\n    def delete_docs(cls, doc_ids, tenant_id):\n        root_folder = FileService.get_root_folder(tenant_id)\n        pf_id = root_folder[\"id\"]\n        FileService.init_knowledgebase_docs(pf_id, tenant_id)\n        errors = \"\"\n        kb_table_num_map = {}\n        for doc_id in doc_ids:\n            try:\n                e, doc = DocumentService.get_by_id(doc_id)\n                if not e:\n                    raise RuntimeError(\"document not found\")\n                tenant_id = DocumentService.get_tenant_id(doc_id)\n                if not tenant_id:\n                    raise RuntimeError(\"Tenant not found!\")\n\n                b, n = File2DocumentService.get_storage_address(doc_id=doc_id)\n\n                TaskService.filter_delete([Task.doc_id == doc_id])\n                if not DocumentService.remove_document(doc, tenant_id):\n                    raise RuntimeError(\"Database error (Document removal)!\")\n\n                f2d = File2DocumentService.get_by_document_id(doc_id)\n                deleted_file_count = 0\n                if f2d:\n                    deleted_file_count = FileService.filter_delete([File.source_type == FileSource.KNOWLEDGEBASE, File.id == f2d[0].file_id])\n                File2DocumentService.delete_by_document_id(doc_id)\n                if deleted_file_count > 0:\n                    settings.STORAGE_IMPL.rm(b, n)\n","sourceCodeStart":697,"sourceCodeEnd":733,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/db/services/file_service.py#L697-L733","documentation":"Raised in FileService.delete_docs when DocumentService.get_by_id(doc_id) returns not-found for one of the submitted document ids. The per-doc try block catches it and appends it to the errors string returned to the caller, so one bad id does not abort the whole batch.","triggerScenarios":"Calling the document deletion API with a doc id that was already deleted, belongs to another tenant, or is malformed; duplicate ids in the list where the first delete removes the doc and the second lookup fails.","commonSituations":"Stale document id in the UI after deletion in another tab; retrying a partially completed delete request; scripts re-running against an already-cleaned dataset.","solutions":["Treat the returned error text as per-file: remove the stale id from the request and re-submit the remainder.","Before deleting, verify each id with DocumentService.get_by_id or the document-list API.","Make deletion idempotent in your client: treat 'document not found' as success.","Check for duplicate ids in the payload."],"exampleFix":"# before\nFileService.delete_docs(['doc1', 'doc1'], tenant_id)  # second lookup fails\n\n# after\nFileService.delete_docs(list(dict.fromkeys(doc_ids)), tenant_id)  # dedupe","handlingStrategy":"try-catch","validationCode":"doc_ids = list(dict.fromkeys(doc_ids))  # dedupe\nvalid_ids = [d for d in doc_ids if DocumentService.get_by_id(d)[0]]","typeGuard":null,"tryCatchPattern":"errors, _ = FileService.delete_docs(doc_ids, tenant_id)\nif 'not found' in errors:\n    # treat as already-deleted: idempotent success\n    pass","preventionTips":["Make client-side deletion idempotent: 'not found' means already deleted.","Deduplicate id lists before submitting batch deletes.","Refresh document lists after deletions instead of reusing stale ids."],"tags":["not-found","delete","document","batch","idempotency"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}