cd /news/large-language-models/why-is-my-llm-stream-empty-a-field-g… · home topics large-language-models article
[ARTICLE · art-119333] src=dev.to ↗ pub= topic=large-language-models verified=true sentiment=· neutral

Why is my LLM stream empty? A field guide to broken SSE responses

A developer has identified four common failure modes that cause empty LLM streams from OpenAI-compatible APIs, including reasoning-only responses, missing finish_reason, malformed SSE framing, and truncated tool calls. To address these issues, the developer built an open-source diagnostic toolkit called agent-stream-doctor that records and analyzes raw streams to pinpoint the failure class automatically.

read3 min views1 publishedSep 2, 2026

If you have ever called an OpenAI-compatible API with streaming enabled and received... nothing, you are not alone. No error, no exception — just a stream that "completes" successfully while your UI stays empty.

After debugging dozens of these cases — and building an open-source toolkit to automate the diagnosis — I keep seeing the same four failure modes. Here is the field guide I wish I had.

Some models emit their entire answer inside a reasoning channel (the "thinking" part) and mark the actual content

channel as empty.

The stream works. Token usage is reported. Your parser is happy. Your UI shows nothing.

python
{"delta": {"reasoning_content": "Let me analyze this..."}, ...}
{"delta": {"content": ""}, "finish_reason": "stop"}
The fix: always inspect the delta fields your model actually uses, not just content. If your client only reads choices[0].delta.content, a reasoning-only response is indistinguishable from an empty one.

2. Missing finish_reason
When a proxy or router truncates the final chunk, finish_reason quietly disappears — and many client libraries silently drop the message instead of raising.

The fix: treat a missing finish_reason as a red flag, not a quirk. Log it. Alert on it. A stream that ends without stop, length, or tool_calls did not end — it was cut.

3. Malformed SSE framing
SSE looks trivial: lines of data: {...} ending with data: [DONE]. But:

multi-byte UTF-8 characters can be split across chunk boundaries
some proxies rewrite or strip the data: prefix
chunks can arrive after [DONE], or the stream can end without it
Each of these breaks parsers quietly — you lose characters in the middle of words, or the client hangs waiting for a terminator that never comes.

The fix: log the raw frames before parsing. When something looks wrong downstream, the raw log is the only witness that tells the truth.

4. Truncated tool calls
Agents assemble tool calls from multiple deltas. If the stream dies halfway, you are left with partial tool_call deltas that never merge into a complete call — and an agent that hangs forever waiting for arguments that will never arrive.

The fix: accumulate arguments across deltas, validate the assembled call, and set a timeout on "hanging" tool states.

The workflow that catches all four
Every one of these bugs shares one property: the protocol layer lies to you. The stream reports success while the payload is broken. So the fix is always the same:

Observe the raw stream first. Reason about the protocol second.

That is exactly why I built agent-stream-doctor — an open-source diagnostic toolkit (Python, zero dependencies for the core) that records raw OpenAI-compatible streams and pinpoints the failure class automatically:

empty streams & reasoning-only responses
missing / inconsistent finish_reason
malformed SSE lines and broken [DONE] sentinels
incomplete tool calls and truncated arguments
pip install git+<https://github.com/Mohammad-Hasan-Kaman/agent-stream-doctor.git>

agent-stream-doctor record --base-url <https://api.example.com/v1/chat/completions> \
  --model your-model --message "Hello!"

agent-stream-doctor analyze stream.txt

It ships with 16 tests running in CI on Python 3.9–3.13, and works offline on captured stream files — so you can diagnose a failure that happened in production last night.

---

*This article was originally published on [my portfolio](https://mhkaman.com/en/articles/why-is-my-llm-stream-empty/), where I write about building AI systems end-to-end. I'm a full-stack developer (Python / Django / C#) open to remote opportunities — say hi on [GitHub](https://github.com/Mohammad-Hasan-Kaman).*
── more in #large-language-models 4 stories · sorted by recency
── more on @openai 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/why-is-my-llm-stream…] indexed:0 read:3min 2026-09-02 ·