Deleting a document orphans its segment-attachment vectors and destroys attachments other documents still reference
还没有人认领这个 Issue。
评估
调研方向
Start with api/tasks/clean_document_task.py and the batch-clean path dispatched from api/services/dataset_service.py:2074, then compare their cleanup flow with delete_segment_from_index_task.py and document_indexing_update_task.py. Run the shared-segment-image case in test_segment_index_cleanup_tasks.py and verify document deletion removes unreferenced attachment vectors, rows, and blobs while preserving attachments still referenced elsewhere.
由索引模型根据 Issue 内容生成。
描述
Self Checks
- I have read the Contributing Guide and Language Policy
- I have searched for existing issues, including closed ones
- I confirm that I am using English to submit this report
Dify version
main at 22aff66cc0
Cloud or Self Hosted
Self Hosted (Source), Cloud
Steps to reproduce
In a multimodal knowledge base, delete a document that has segments with attachments. Both deletion paths mishandle those attachments: clean_document_task (single delete, dispatched from api/events/event_handlers/clean_when_document_deleted.py:13) and batch_clean_document_task (batch delete, dispatched from api/services/dataset_service.py:2074).
1. The attachment vectors are never removed.
Attachment vectors are written under doc_id == UploadFile.id (api/core/rag/datasource/vdb/vector_factory.py:201,209), but the node id list handed to index_processor.clean is built only from DocumentSegment.index_node_id:
# api/tasks/clean_document_task.py:64
index_node_ids = [segment.index_node_id for segment in segments if segment.index_node_id]
so the attachment vectors outlive the document permanently. RetrievalService.get_segment_attachment_infos then finds no UploadFile/binding for them and drops them silently, so they keep consuming top-k slots and quietly degrade recall for every subsequent query against that collection.
2. An attachment another document still references is destroyed.
SegmentAttachmentBinding.attachment_id is a user-supplied UploadFile id copied verbatim in SegmentService.create_segment (api/services/dataset_service.py:3512-3521) and carries no uniqueness constraint, so the same image may legitimately be bound to segments of several documents. Both tasks delete the UploadFile row and its storage blob for every binding the deleted document held, with no check for bindings that survive — and in the single-delete path the UploadFile delete even runs before the binding delete:
# api/tasks/clean_document_task.py:137-145
if attachment_ids:
session.execute(delete(UploadFile).where(UploadFile.id.in_(attachment_ids)))
if binding_ids:
session.execute(delete(SegmentAttachmentBinding).where(SegmentAttachmentBinding.id.in_(binding_ids)))
The rest of the codebase already treats this as the contract. delete_segment_from_index_task.py:86-121 and document_indexing_update_task.py:103-150 both delete the bindings, flush(), recompute orphan_attachment_ids from the bindings that remain, clean only those from the vector store, and only then drop the rows and blobs. test_segment_index_cleanup_tasks.py even has a shared-segment-image case pinning it. The two document-deletion tasks are the only paths that skip both steps.
✔️ Expected Behavior
Deleting a document removes the vectors, rows and blobs of the attachments nothing else references, and leaves attachments that another document still binds untouched — the same contract delete_segment_from_index_task already implements.
❌ Actual Behavior
Attachment vectors are orphaned in the collection forever, and an attachment shared with another document has its row and blob deleted out from under that document, so the surviving document's segment renders a broken attachment.
- 主要语言
- TypeScript
- 星标
- 157k
- 派生
- 24.7k
- 平均合并
- 22 小时 32 分钟
- 30 天内合并 PR
- 611
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
langgenius/dify 的其他 Issue
-
Annotation Reply: a stored score threshold of 0.0 is silently replaced with 1, disabling the feature 未关闭
难度 2/5 1-3 小时 新手友好度 88/100
langgenius/dify#42639 · 1 条评论 · 1 个 reaction ·
-
难度 2/5 1-3 小时 新手友好度 70/100
langgenius/dify#42468 · 1 条评论 · 1 个 reaction ·
-
🐞 bug
难度 2/5 1-3 小时 新手友好度 86/100
langgenius/dify#42446 · 1 个 reaction ·
-
难度 2/5 1-3 小时 新手友好度 88/100
langgenius/dify#42355 · 1 条评论 · 1 个 reaction ·
-
难度 2/5 1-3 小时 新手友好度 88/100
langgenius/dify#42350 · 1 条评论 · 1 个 reaction ·
相似的 Issue
-
calcite-components needs triage refactor
难度 2/5 1-3 小时 新手友好度 75/100
Esri/calcite-design-system#15203 ·
-
难度 2/5 1-3 小时 新手友好度 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
难度 1/5 1 小时以内 新手友好度 95/100
-
难度 2/5 1-3 小时 新手友好度 78/100
Automattic/studio#4908 ·
-
难度 2/5 1-3 小时 新手友好度 90/100