[Bug] Service API cannot re-enable a segment with Elasticsearch after disabling it (regression of #10445)
- Dominant language
- TypeScript
- Stars
- 156k
- Forks
- 24.6k
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 610
Description
### Self Checks
- [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report, otherwise it will be closed.
- [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
- [x] Please do not modify this template :) and fill in all the required fields.
### Dify version
1.16.0
### Cloud or Self Hosted
Self Hosted (Docker)
### Steps to reproduce
1. Configure a self-hosted Dify instance to use Elasticsearch as the vector store.
2. Create a high-quality knowledge base with a paragraph-indexed document and wait until its segments are indexed successfully.
3. Disable an enabled segment through the Knowledge Service API:
```http
POST /v1/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}
Authorization: Bearer
Content-Type: application/json
{"segment":{"enabled":false}}
```
4. Wait for `disable_segment_from_index_task` to finish. The vector is removed successfully from Elasticsearch.
5. Re-enable the same segment through the Knowledge Service API without changing its content:
```http
POST /v1/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}
Authorization: Bearer
Content-Type: application/json
{"segment":{"enabled":true}}
```
6. 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:
```text
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__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.
- Original issue: https://github.com/langgenius/dify/issues/10373
- Original fix: https://github.com/langgenius/dify/pull/10445
Contributor guide
Research direction
Trace DatasetService.update_segment() in api/services/dataset_service.py, then inspect VectorService.update_segment_vector() and the Elasticsearch adapter in api/providers/vdb/vdb-elasticsearch/src/dify_vdb_elasticsearch/elasticsearch_vector.py. Reproduce the disable/re-enable sequence with Elasticsearch and verify that re-enabling an unchanged segment recreates its vector, preserves enabled=true, and does not leave status=error when the vector is already missing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elasticsearch, python
- Domain
- api, backend, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100