Self Checks
Dify version
1.16.0
Cloud or Self Hosted
Self Hosted (Docker)
Steps to reproduce
- Configure a self-hosted Dify instance to use Elasticsearch as the vector store.
- Create a high-quality knowledge base with a paragraph-indexed document and wait until its segments are indexed successfully.
- Disable an enabled segment through the Knowledge Service API:
POST /v1/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}
Authorization: Bearer <dataset-api-key>
Content-Type: application/json
{"segment":{"enabled":false}}
- Wait for
disable_segment_from_index_task to finish. The vector is removed successfully from Elasticsearch.
- Re-enable the same segment through the Knowledge Service API without changing its content:
POST /v1/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}
Authorization: Bearer <dataset-api-key>
Content-Type: application/json
{"segment":{"enabled":true}}
- The API responds with HTTP 200, but the returned/persisted segment is disabled and has
status=error.
The API/worker logs show the following sanitized call chain:
update segment index failed
DatasetService.update_segment(...)
VectorService.update_segment_vector(...)
vector.delete_by_ids([segment.index_node_id])
ElasticsearchVector.delete_by_ids(...)
elasticsearch.NotFoundError: NotFoundError(404, 'not_found',
'{"_index":"Vector_index_<redacted>_Node",
"_id":"<index_node_id>","result":"not_found"}')
Re-enabling the same segment from the Dify Web console succeeds. The Web console uses update_segments_status() and enable_segments_to_index_task, which reloads the vector instead of first deleting the already-missing vector.
✔️ Expected Behavior
Re-enabling a segment through the Knowledge Service API should recreate/reload the segment vector and leave the segment with enabled=true and a non-error status.
Re-enabling should also be idempotent when the vector has already been removed by the preceding disable task. A missing vector during this flow should not abort re-indexing.
❌ Actual Behavior
In Dify 1.16.0, the unchanged-content branch of DatasetService.update_segment() calls VectorService.update_segment_vector() when args.enabled is true:
https://github.com/langgenius/dify/blob/1.16.0/api/services/dataset_service.py#L3599-L3602
update_segment_vector() unconditionally deletes the existing vector before adding it:
https://github.com/langgenius/dify/blob/1.16.0/api/services/vector_service.py#L131-L135
The Elasticsearch adapter calls client.delete() without ignoring a missing-document 404:
https://github.com/langgenius/dify/blob/1.16.0/api/providers/vdb/vdb-elasticsearch/src/dify_vdb_elasticsearch/elasticsearch_vector.py#L182-L186
Because the disable task has already removed the vector, the second delete returns 404 not_found. The exception prevents add_texts() from running. DatasetService.update_segment() then catches the exception, sets enabled=false and status=error, commits that state, and returns normally:
https://github.com/langgenius/dify/blob/1.16.0/api/services/dataset_service.py#L3787-L3797
This appears to be a regression of #10373 / #10445. PR #10445 handled re-enabling unchanged content by calling VectorService.create_segments_vector() directly. The Dify 1.16.0 path now calls update_segment_vector() instead, reintroducing the failure for Elasticsearch.
Self Checks
Dify version
1.16.0
Cloud or Self Hosted
Self Hosted (Docker)
Steps to reproduce
disable_segment_from_index_taskto finish. The vector is removed successfully from Elasticsearch.status=error.The API/worker logs show the following sanitized call chain:
Re-enabling the same segment from the Dify Web console succeeds. The Web console uses
update_segments_status()andenable_segments_to_index_task, which reloads the vector instead of first deleting the already-missing vector.✔️ Expected Behavior
Re-enabling a segment through the Knowledge Service API should recreate/reload the segment vector and leave the segment with
enabled=trueand a non-error status.Re-enabling should also be idempotent when the vector has already been removed by the preceding disable task. A missing vector during this flow should not abort re-indexing.
❌ Actual Behavior
In Dify 1.16.0, the unchanged-content branch of
DatasetService.update_segment()callsVectorService.update_segment_vector()whenargs.enabledis true:https://github.com/langgenius/dify/blob/1.16.0/api/services/dataset_service.py#L3599-L3602
update_segment_vector()unconditionally deletes the existing vector before adding it:https://github.com/langgenius/dify/blob/1.16.0/api/services/vector_service.py#L131-L135
The Elasticsearch adapter calls
client.delete()without ignoring a missing-document 404:https://github.com/langgenius/dify/blob/1.16.0/api/providers/vdb/vdb-elasticsearch/src/dify_vdb_elasticsearch/elasticsearch_vector.py#L182-L186
Because the disable task has already removed the vector, the second delete returns
404 not_found. The exception preventsadd_texts()from running.DatasetService.update_segment()then catches the exception, setsenabled=falseandstatus=error, commits that state, and returns normally:https://github.com/langgenius/dify/blob/1.16.0/api/services/dataset_service.py#L3787-L3797
This appears to be a regression of #10373 / #10445. PR #10445 handled re-enabling unchanged content by calling
VectorService.create_segments_vector()directly. The Dify 1.16.0 path now callsupdate_segment_vector()instead, reintroducing the failure for Elasticsearch.