ChunkChatCompletionResponse doesn't end at \n\n #19812

Closed
opened 2026-02-21 20:04:14 -05:00 by yindo · 3 comments
Owner

Originally created by @Mutantpenguin on GitHub (Oct 22, 2025).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.9.1

Cloud or Self Hosted

Cloud

Steps to reproduce

  1. Send a valid POST to /chat-messages in streaming mode. Doesn't matter if manually via axios or through the npm package dify-client.
  2. The chunks you get back don't end at \n\n as described in the documentation.
  const difyInstance = axios.create({
    baseURL: "https://api.dify.ai/v1",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
    },
    responseType: "stream",
  })

  const parameters = {
    inputs: {},
    query: text,
    user: user,
    response_mode: "streaming",
    conversation_id: state.difyConversationId
  }

  const response = await difyInstance.post(
    "/chat-messages",
    parameters,
  )

  const stream = response.data;

  const decoder = new TextDecoder();

  stream.on('data', async (chunk) => {
    // we get a Uint8Array here that we have to decode
    // it often doesn't end with `\n\n`, but somewhere inside a message
    const chunkStr = decoder.decode(chunk);
  });

✔️ Expected Behavior

Each message (so each chunk of the stream) ends with \n\n and is therefore a complete and valid message in itself.

Actual Behavior

Whe using the /chat-messages endpoint in streaming mode, the returned chunks don't only end at \n\n as described in the documentation, but seemingly at random intervals and also at \n\n.

Because of this, 1 message can be broken up into 2 chunks and a user of this endpoint has to manually reconstruct valid messages.

Please either change this so that each chunk always ends at \n\n, or fix the documentation.

I don't mean the documentation at https://docs.dify.ai/api-reference/chatflow/send-chat-message#send-chat-message, but the one available from inside an app on the left side called "API Access".

Btw: At one place it's called ChunkChatCompletionResponse and ChunkAdvancedChatEvent at the other.

Originally created by @Mutantpenguin on GitHub (Oct 22, 2025). ### 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.9.1 ### Cloud or Self Hosted Cloud ### Steps to reproduce 1. Send a valid POST to `/chat-messages` in streaming mode. Doesn't matter if manually via axios or through the npm package `dify-client`. 2. The chunks you get back don't end at `\n\n` as described in the documentation. ```javascript const difyInstance = axios.create({ baseURL: "https://api.dify.ai/v1", headers: { Authorization: `Bearer ${API_KEY}`, }, responseType: "stream", }) const parameters = { inputs: {}, query: text, user: user, response_mode: "streaming", conversation_id: state.difyConversationId } const response = await difyInstance.post( "/chat-messages", parameters, ) const stream = response.data; const decoder = new TextDecoder(); stream.on('data', async (chunk) => { // we get a Uint8Array here that we have to decode // it often doesn't end with `\n\n`, but somewhere inside a message const chunkStr = decoder.decode(chunk); }); ``` ### ✔️ Expected Behavior Each message (so each chunk of the stream) ends with `\n\n` and is therefore a complete and valid message in itself. ### ❌ Actual Behavior Whe using the `/chat-messages` endpoint in streaming mode, the returned chunks don't only end at `\n\n` as described in the documentation, but seemingly at random intervals and also at `\n\n`. Because of this, 1 message can be broken up into 2 chunks and a user of this endpoint has to manually reconstruct valid messages. Please either change this so that each chunk always ends at `\n\n`, or fix the documentation. I don't mean the documentation at https://docs.dify.ai/api-reference/chatflow/send-chat-message#send-chat-message, but the one available from inside an app on the left side called "API Access". Btw: At one place it's called `ChunkChatCompletionResponse` and `ChunkAdvancedChatEvent` at the other.
yindo added the 🐞 bug label 2026-02-21 20:04:14 -05:00
yindo closed this issue 2026-02-21 20:04:14 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Oct 22, 2025):

Hi @Mutantpenguin! I'm Dosu and I’m helping the dify team.

This is a documentation issue, not an implementation bug. The streaming API for /chat-messages uses Server-Sent Events (SSE), where each logical message is framed by a double newline (\n\n). However, the actual TCP chunks you receive may split or combine these messages arbitrarily due to network and server buffering—so you can't rely on each chunk ending at \n\n as the docs suggest. Instead, you need to accumulate data and split on \n\n to reconstruct complete messages on the client side, which is standard for SSE streaming APIs [discussion].

The inconsistent use of ChunkChatCompletionResponse and ChunkAdvancedChatEvent in docs and code is a known source of confusion, but both refer to the same JSON event objects sent in the stream. There’s no evidence of a fix that enforces chunk boundaries at \n\n—the recommended approach is client-side reconstruction [issue].

If you want this behavior clarified, updating the documentation to reflect how SSE chunking actually works would be the right move.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Oct 22, 2025): <!-- Greeting --> Hi @Mutantpenguin! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the dify team. <!-- Answer --> This is a documentation issue, not an implementation bug. The streaming API for `/chat-messages` uses Server-Sent Events (SSE), where each logical message is framed by a double newline (`\n\n`). However, the actual TCP chunks you receive may split or combine these messages arbitrarily due to network and server buffering—so you can't rely on each chunk ending at `\n\n` as the docs suggest. Instead, you need to accumulate data and split on `\n\n` to reconstruct complete messages on the client side, which is standard for SSE streaming APIs [[discussion](https://github.com/langgenius/dify/discussions/23229)]. The inconsistent use of `ChunkChatCompletionResponse` and `ChunkAdvancedChatEvent` in docs and code is a known source of confusion, but both refer to the same JSON event objects sent in the stream. There’s no evidence of a fix that enforces chunk boundaries at `\n\n`—the recommended approach is client-side reconstruction [[issue](https://github.com/langgenius/dify/issues/17769)]. If you want this behavior clarified, updating the documentation to reflect how SSE chunking actually works would be the right move. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/53d7c5ff-1549-48fe-95d7-d5c7c6909335?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/27260)
Author
Owner

@Mutantpenguin commented on GitHub (Oct 22, 2025):

@dosu

Thanks, I can work with that.

I would still leave this issue open then to get the documentation fixed.

@Mutantpenguin commented on GitHub (Oct 22, 2025): @dosu Thanks, I can work with that. I would still leave this issue open then to get the documentation fixed.
Author
Owner

@dosubot[bot] commented on GitHub (Oct 22, 2025):

Sounds good—leaving this open for documentation clarity makes sense. I checked and there aren’t any recent documentation fixes for this chunk boundary behavior, so your feedback is still relevant. If anything changes or an update lands, I’ll let you know.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Oct 22, 2025): <!-- Answer --> Sounds good—leaving this open for documentation clarity makes sense. I checked and there aren’t any recent documentation fixes for this chunk boundary behavior, so your feedback is still relevant. If anything changes or an update lands, I’ll let you know. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/0679cdae-5a22-4f81-adbc-e68e3550419b?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/27260)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#19812