google-gemini / google-gemini/gemini-cli
bug: final SSE event discarded when stream ends without a trailing blank line (no EOF flush)
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
## What happened?
The SSE parser in `CodeAssistServer.requestStreamingPost()` only yields a buffered event when it encounters a **blank line**. Per the SSE specification, a pending event must also be dispatched at EOF; here, when the connection closes immediately after the final `data: {...}` line without a terminating `\n\n` (truncation or a non-conformant proxy), the loop exits and `bufferedLines` is silently discarded — typically losing the chunk that carries `finishReason`/usage metadata, degrading the turn without any error or log.
## Affected code
`packages/core/src/code_assist/server.ts:498-520`:
```ts
let bufferedLines: string[] = [];
for await (const line of rl) {
if (line.startsWith('data: ')) {
bufferedLines.push(line.slice(6).trim());
} else if (line === '') {
// ... yield JSON.parse(chunk) ...
bufferedLines = [];
}
// Ignore other lines
}
// loop exit: bufferedLines never flushed
```
## How can this be reproduced?
Point the Code Assist endpoint at a server/proxy that closes the response right after emitting `data: {…}` with no trailing blank line (e.g., `echo -n 'data: {"candidates":[...]}' | nc -l …`). The generator ends having never yielded that final object.
## What did you expect to happen?
After the read loop completes, any remaining buffered lines should be parsed and yielded (spec-compliant EOF dispatch), or at minimum trigger a logged truncation warning.
## Impact
Silently truncated model turns on flaky networks/intermediaries — responses missing their finishReason look like empty completions.
## Suggested direction
After the `for await` loop, flush `bufferedLines` through the same parse/yield path (with the same malformed-JSON logging), before returning.
---
*Found by source audit on current `main` (commit `5411f113c`); platform-independent. No open issue/PR covering this was found (searched: SSE streaming final event EOF).*
Contributor guide
Research direction
Start in packages/core/src/code_assist/server.ts at CodeAssistServer.requestStreamingPost(), especially lines 498-520, and trace how bufferedLines are handled on blank lines and loop exit. Verify that a final data event without a trailing blank line is emitted at EOF, while malformed-JSON logging remains consistent with the existing parsing path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100