Issues / #1392
#1392 Web app: an assistant reply with no content is dropped from the conversation history (reasoning models repeat themselves)
closed · @demetree · 1 comments · View on GitHub
Description
### What happens
An assistant reply with no `content` is silently removed from the conversation history the next request sends, so
the model is asked the new question with no record of the turn that is still visible in the chat. On a reasoning
model the effect is the model re-opening the same reasoning, which reads as the answer repeating itself
(`Hi Hi hi Fib Fib…`) instead of continuing.
### Where
`serve/web/app.js`, `assistantMessages()`:
```js
function assistantMessages(m) {
const ran = (m.tools || []).filter(...);
if (!ran.length) return m.text ? [{role: "assistant", content: m.text}] : [];
```
`m.text` is built only from `delta.content` (line 831); `delta.reasoning_content` goes to `m.reasoning` (line 825).
So whenever a turn ends before its first content token, `m.text` is `""` and the `[]` branch drops the whole turn.
`apiMessages()` (line 721) then emits two consecutive user messages - or a user message with no assistant turn above
it at all.
### Steps to see it
1. Open the web app, ask anything with `Thinking` on.
2. Stop the reply while it is still thinking (before any answer text appears). The reply stays in the chat, showing
only the reasoning.
3. Ask a follow-up.
The follow-up is sent without that turn. Compare with the same conversation where you let the reply finish: the
history keeps the assistant turn and the follow-up continues from it.
The same happens without pressing Stop whenever a turn ends with no content - for example a request that hits the
context or `max_tokens` limit during thinking. Through the API the same state is visible directly: the response
comes back as `{"content": null, "reasoning_content": "..."}` with `finish_reason: "length"`, and the web app stores
exactly that turn as empty.
### Expected
A turn the user can see in the chat is not silently dropped from the history. Either keep the assistant turn (with
its reasoning, or with an explicit marker that it was empty), or say why it cannot be sent back.
### Notes
- `m.reasoning` is never sent back either, which is fine on its own for a model that puts everything in `content`,
but it means a reasoning-only turn has nothing at all to contribute to the next request.
- The tool-call path (the `ran.length` branch) already handles empty text, so this is specific to the no-tools case.
Related on strata.com
Editorial links to help you install, pick models, or read release notes — not part of the upstream thread.