Skip to content

Stream buffers drop a final line/event not terminated by \n at EOF — terminal finish_reason: Length can be lost #313

Description

@hherb

Found during the PR #306 code review (finding 6 of the report-only list). Low priority — mainstream servers newline-terminate — but the failure is silent when it hits.

The behaviour

All three stream buffers require a terminator to yield their last unit, and none of the consumers drain residual bytes on EOF:

  • NdjsonBuffer::pop_line (src/crates/primer-inference/src/ollama.rs) requires \n; the stream-end arm never drains leftover bytes in buf.
  • OpenAiSseBuffer::pop_data (src/crates/primer-inference/src/openai_compat/mod.rs) likewise.
  • Cloud's SseBuffer (src/crates/primer-inference/src/cloud.rs) needs the trailing blank line of an SSE event.

If a server flushes its terminal payload — {"done":true,"done_reason":"length"} or data: [DONE] — without a trailing newline before closing the connection, that real terminal chunk is discarded. The synthetic abrupt-EOF flush chunk carries default FinishReason::Stop, so a genuine Length truncation loses its signal and the dialogue manager's context-limit recovery ladder never fires for that turn.

Suggested resolution

On the None (EOF) arm, drain any residual buffered bytes as a final line/payload before feeding the synthetic done chunk. Tests: a terminal NDJSON line without \n, and a data: [DONE] without trailing newline.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions