langgenius / langgenius/dify

[Bug] Service API cannot re-enable a segment with Elasticsearch after disabling it (regression of #10445)

Open
#39,988 1 comment 1 reaction 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.