Hmbown/CodeWhale · error · anyhow::Error
Chat Completions stream closed before [DONE] or…
Error message
Chat Completions stream closed before [DONE] or finish_reason
What it means
After the SSE stream ends normally (no transport failure), the code checks whether a `[DONE]` sentinel or a `finish_reason` was observed. If neither appeared, the stream closed prematurely — the generation never formally terminated — so this error is yielded instead of `MessageStop`.
Solutions
- Treat as an incomplete generation: check whether the assistant message content is usable or should be retried
- Check server/proxy (nginx `proxy_read_timeout`, LB idle) timeouts and raise them
- Verify the OpenAI-compatible server sends a terminating `finish_reason` chunk and `[DONE]`
- Retry the request; enable streaming retry logic
Example fix
// before: nginx closing long idle streams proxy_read_timeout 60s; // after proxy_read_timeout 300s; proxy_buffering off;
Defensive patterns
Strategy: retry
Try / catch
match result {
Err(e) if e.to_string().contains("closed before [DONE]") => {
// incomplete generation: retry, or surface partial output with a warning
retry_with_backoff(e);
}
other => propagate(other),
} Prevention
- Raise nginx/LB proxy_read_timeout and disable proxy_buffering for SSE
- Verify the server sends a final finish_reason chunk plus [DONE]
- Enable stream-level retry for clean reconnects
- Monitor provider status pages for mid-stream abort incidents
When it happens
Trigger: The server closes the connection after partial output without sending `data: [DONE]` and without any choice carrying a `finish_reason` — e.g. server-side abort, max-tokens kill without a final chunk, proxy closing idle keep-alive early, or an OpenAI-compatible server that ends streams uncleanly.
Common situations: vLLM/Ollama or other self-hosted servers dropping the final chunk under load; reverse proxies (nginx) closing streams on idle timeouts; provider outages truncating generations.
Related errors
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/80a18e81c3594115.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client/chat.rs:1688
yield Ok(event);
}
}
}
}
}
// Close any open blocks — content_index points to the
// currently active open block (it is only incremented
// *after* a block is closed, not when opened).
if thinking_started || text_started {
yield Ok(StreamEvent::ContentBlockStop { index: content_index });
}
release_stream_buffer(byte_buf);
if !stream_failed && (saw_done || saw_finish_reason) {
yield Ok(StreamEvent::MessageStop);
} else if !stream_failed {
yield Err(anyhow::anyhow!(
"Chat Completions stream closed before [DONE] or finish_reason"
));
}
};
Ok(Pin::from(Box::new(stream)
as Box<
dyn futures_util::Stream<Item = Result<StreamEvent>> + Send,
>))
}
}
// === Chat Completions Helpers ===
#[cfg(test)]
pub(super) fn build_chat_messages(
system: Option<&SystemPrompt>,
messages: &[Message],View on GitHub (pinned to 73e0f67d83)