If you’re using Server-Sent Events (SSE) and notice missing text in your event stream messages, especially when newlines (\n
) are involved, you’re not alone. I recently faced a frustrating issue where any text after a newline in a single SSE message was getting lost on the client side when using fetchEventSource
in JavaScript. After extensive debugging, I discovered the root cause and a reliable fix. In this blog post, I’ll explain the issue and how you can prevent unexpected data loss in your SSE implementation.
The Issue: Newlines Causing Data Loss in SSE Messages
I was streaming AI-generated responses using a C# backend and fetchEventSource
on the client side. Occasionally, AI responses contained newline characters (\n
). However, when the client received the response, any text after the first newline was getting lost.
Sample Problematic Code (C# Server-Side SSE Implementation):
await foreach (var res in chatclient.CompleteChatStreamingAsync(chatmessages, options))
{
if (cancellationToken.IsCancellationRequested)
{
yield return "";
yield break;
}
foreach (var cu in res.ContentUpdate)
{
if (cu.Kind == ChatMessageContentPartKind.Text)
{
yield return cu.Text; // AI-generated text with possible newlines
}
}
}
This worked fine for most cases but failed when cu.Text
contained newlines (\n
). The client-side JavaScript receiving these messages would discard any content after the newline.
Why This Happens
Server-Sent Events (SSE) require each line in a message to be prefixed with data:
. If a single message contains multiple lines without prefixing each line, anything after the first newline is ignored.
Example of incorrect SSE formatting:
data: First line
Second line
Third line
Only “First line” would be received by the client.
The Fix: Splitting Messages at Newlines
To ensure every line is properly transmitted, I modified the server-side logic to split multiline responses before sending them.
Updated C# Server Code:
await foreach (var res in chatclient.CompleteChatStreamingAsync(chatmessages, options))
{
if (cancellationToken.IsCancellationRequested)
{
yield return "";
yield break;
}
foreach (var cu in res.ContentUpdate)
{
if (cu.Kind == ChatMessageContentPartKind.Text)
{
await foreach (var sp in ProcessNewLines(cu.Text))
{
yield return sp;
}
}
}
}
public async IAsyncEnumerable<string> ProcessNewLines(string s)
{
string[] list = s?.Split('\n') ?? [""];
foreach (var item in list)
{
yield return item; // Send each line separately
}
}
Alternative Fix: Using a Placeholder Instead of Splitting
If you want to preserve the original newlines and reintroduce them on the client, you can send a placeholder ([[NEWLINE]]
) and replace it on the client side.
Modified C# Server Code with Placeholder
await foreach (var res in chatclient.CompleteChatStreamingAsync(chatmessages, options))
{
if (cancellationToken.IsCancellationRequested)
{
yield return "";
yield break;
}
foreach (var cu in res.ContentUpdate)
{
if (cu.Kind == ChatMessageContentPartKind.Text)
{
yield return cu.Text.Replace("\n", "[[NEWLINE]]");
}
}
}
Handling it on the Client Side:
On the frontend, when receiving the event stream data, simply revert the placeholder back to \n
:
onmessage(ev) {
let receivedText = ev.data.replaceAll("[[NEWLINE]]", "\n");
_this.mcqForm.patchValue({
explanationText: _this.mcqForm.value.explanationText + receivedText
});
}
This ensures that the entire message, including newlines, is correctly reconstructed on the client side.
Conclusion
The issue of newlines causing data loss in fetchEventSource
is a common pitfall when using SSE. By splitting the message at newlines or using a placeholder approach, you can ensure that your client receives all the data correctly.
If you’re dealing with SSE streaming and notice missing text, be sure to check if newlines are causing unexpected behavior!
Have you encountered a similar issue? Let me know in the comments below!

Amit Mittal is a seasoned tech entrepreneur and software developer specializing in SaaS, web hosting, and cloud solutions. As the founder of Bitss Techniques, he brings over 15 years of experience in delivering robust digital solutions, including CMS development, custom plugins, and enterprise-grade services for the education and e-commerce sectors.