Files
letta-server/letta/server/rest_api
cthomas 2a2e777807 fix: ensure stop_reason is always set and reduce noisy logs (#9046)
fix: consume [DONE] token after error events to prevent forced finalizer append

**Problem:**
Stream finalizer was frequently logging warning and appending forced [DONE]:
```
[Stream Finalizer] Appending forced [DONE] for run=run-xxx (saw_error=True,
saw_done=False, final_stop_reason=llm_api_error)
```

This happened on every error, even though streaming_service.py already yields
[DONE] after all error events.

**Root Cause:**
Line 266: `is_done = saw_done or saw_error` caused loop to break immediately
after seeing error event, BEFORE consuming the [DONE] chunk that follows:

```python
is_done = saw_done or saw_error
await writer.write_chunk(...)
if is_done:  # Breaks on error!
    break
```

Sequence:
1. streaming_service.py yields: `event: error\ndata: {...}\n\n`
2. Redis reader sees error → sets `saw_error=True`
3. Sets `is_done=True` and breaks
4. Never reads next chunk: `data: [DONE]\n\n`
5. Finalizer runs → `saw_done=False` → appends forced [DONE]

**Fix:**
1. Only break when `saw_done=True` (not `saw_error`) → allows consuming [DONE]
2. Only run finalizer when `saw_done=False` → reduces log noise

**Result:**
- [DONE] now consumed naturally from streaming_service.py error handlers
- Finalizer warning only appears when truly needed (fallback cases)
- Cleaner production logs

👾 Generated with [Letta Code](https://letta.com)

Co-authored-by: Letta <noreply@letta.com>
2026-01-29 12:44:04 -08:00
..
2025-09-17 15:47:40 -07:00
2025-09-17 15:47:40 -07:00
2025-09-17 15:47:40 -07:00
2025-09-17 15:47:40 -07:00
2025-09-17 15:47:40 -07:00