langgenius / langgenius/dify

Bug: Service API QA segment updates clear the answer when it is omitted

Open
#41,315 0 comments 1 reaction 0 assignees View on GitHub
🐞 bug 1.17.0
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.17.0

### Cloud or Self Hosted

Self Hosted (Source)

### Steps to reproduce

1. Run Dify Self Hosted from source at commit `1299d99b2d70b1b639819248715dd3340979665f`.

2. Create or select a knowledge base with a document in QA mode (`doc_form=qa_model`). Create a completed and enabled segment with content `old question` and answer `old answer`.

3. Using a dataset API key, update only the content through the Service API:

```http
POST /v1/datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}
Authorization: Bearer
Content-Type: application/json

{"segment": {"content": "new question"}}
```

4. Retrieve the segment and inspect `answer`, `status`, `enabled`, and `error`.

5. Repeat with the high-quality indexing technique. A keywords-only partial update also reproduces the answer loss:

```json
{"segment": {"keywords": ["new keyword"]}}
```

This was verified through the real Service API `SegmentService.update_segment` path with a real SQLAlchemy SQLite session.

### ✔️ Expected Behavior

The API should not mutate an existing QA segment when a required `answer` is missing.

Please confirm which contract is intended:

1. If QA updates require an answer, reject the request with a clear HTTP 400 validation error before mutation or indexing, and leave the existing segment unchanged. The schema and API documentation should state that `answer` is required for QA updates.

2. If partial updates are supported, an omitted `answer` should preserve the existing answer. An explicitly supplied answer should replace it, with the behavior for `null` or an empty string documented.

### ❌ Actual Behavior

The request is accepted, but an omitted answer is converted to `None` and written into the segment.

- Economy indexing: the existing answer is persisted as `null` while the segment remains `completed` and enabled. This causes silent data loss.
- High-quality indexing: the update attempts to concatenate the content with `None`, causing `can only concatenate str (not "NoneType") to str`. The exception is caught internally; the segment is persisted as `error` and disabled, while the Service API still returns HTTP 200.
- A keywords-only update has the same answer-clearing behavior.

The relevant code currently allows an optional answer in `SegmentUpdateArgs`:
https://github.com/langgenius/dify/blob/main/api/services/entities/knowledge_entities/knowledge_entities.py#L253

The QA update path then assigns `segment.answer = args.answer`:
https://github.com/langgenius/dify/blob/main/api/services/dataset_service.py#L3713

Local focused verification passed: Service API controller tests (111), SegmentService tests (42), and update_segment focused tests (13). Existing tests did not cover a QA partial update with an omitted answer.

Related context: Issue #6251 documents `answer` as required when creating a QA document; this report concerns the inconsistent behavior of the Service API segment update endpoint.

If maintainers confirm this issue is valid, please assign this issue to me so I can prepare the PR. I will wait for confirmation before opening the PR.

Contributor guide

Open the contributing guide

Research direction

Start with SegmentUpdateArgs in api/services/entities/knowledge_entities/knowledge_entities.py and the QA update path in api/services/dataset_service.py. Run the listed Service API controller, SegmentService, and update_segment tests, then add focused coverage for omitted answers on QA and keywords-only updates. Done means the agreed validation or preservation contract is enforced without mutating the existing segment.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sqlalchemy, sqlite
Domain
api, backend, database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.