eve version
Observed on eve@0.30.8. Code inspection of 0.31.1 (all 18 commits in eve@0.30.8...eve@0.31.1) shows no changes to the affected path, so it should reproduce there too.
Where does the bug occur?
Production (eve build + eve start, self-hosted k8s) — direct Anthropic provider (@ai-sdk/anthropic, model claude-sonnet-5), Slack channel, adaptive thinking (display omitted).
Describe the bug
In multi-turn Slack sessions that include an answered HITL interaction (an ask_question answer or a tool-approval response), the next model call can fail with:
This model does not support assistant message prefill. The conversation must end with a user message.
eve treats the 400 as terminal (session.failed → "This session couldn't recover"), permanently retiring the session — in a Slack DM this effectively bricks the user's conversation surface.
The failing request (from the harness error dump) ends with an assistant message containing only an empty thinking block (thinking: '' plus signature — Sonnet 5 with omitted thinking display), i.e. the model's previous response contained no text and no tool call, eve appended it to history, and the follow-up call was issued with the conversation ending on that assistant turn. Anthropic 4.6+ models reject that shape unconditionally.
This is the same failure class as #80 (fixed for the compaction path by #175, which appends a synthetic Continue. user turn). The path here appears to be different — plausibly the empty-response reissue in the tool loop — and is not covered by that guard.
Repro sketch
- Slack channel session,
claude-sonnet-5, adaptive thinking (default display).
- Drive a conversation into a HITL prompt (e.g. a tool with
approval: always() or a model-initiated ask_question), answer it via the Slack button/reply.
- Continue the conversation with a multi-step request. When the model returns a thinking-only/empty response after the resume, the next call 400s and the session terminally fails.
Not deterministic (depends on the model emitting an empty/thinking-only completion), but frequent enough that one user hit it three times in an evening on fresh sessions.
Workaround we're running
AI SDK middleware on the wrapped model that mirrors #175's repair globally: if params.prompt ends with an assistant message, append { role: 'user', content: [{ type: 'text', text: 'Continue.' }] }. This eliminated the failures. Suggests the fix is to apply the existing trailing-assistant guard at the single point where the harness finalizes prompts, rather than per-path.
Happy to provide redacted request dumps or test the fix.
eve version
Observed on
eve@0.30.8. Code inspection of0.31.1(all 18 commits ineve@0.30.8...eve@0.31.1) shows no changes to the affected path, so it should reproduce there too.Where does the bug occur?
Production (
eve build+eve start, self-hosted k8s) — direct Anthropic provider (@ai-sdk/anthropic, modelclaude-sonnet-5), Slack channel, adaptive thinking (display omitted).Describe the bug
In multi-turn Slack sessions that include an answered HITL interaction (an
ask_questionanswer or a tool-approval response), the next model call can fail with:eve treats the 400 as terminal (
session.failed→ "This session couldn't recover"), permanently retiring the session — in a Slack DM this effectively bricks the user's conversation surface.The failing request (from the harness error dump) ends with an assistant message containing only an empty thinking block (
thinking: ''plus signature — Sonnet 5 with omitted thinking display), i.e. the model's previous response contained no text and no tool call, eve appended it to history, and the follow-up call was issued with the conversation ending on that assistant turn. Anthropic 4.6+ models reject that shape unconditionally.This is the same failure class as #80 (fixed for the compaction path by #175, which appends a synthetic
Continue.user turn). The path here appears to be different — plausibly the empty-response reissue in the tool loop — and is not covered by that guard.Repro sketch
claude-sonnet-5, adaptive thinking (default display).approval: always()or a model-initiatedask_question), answer it via the Slack button/reply.Not deterministic (depends on the model emitting an empty/thinking-only completion), but frequent enough that one user hit it three times in an evening on fresh sessions.
Workaround we're running
AI SDK middleware on the wrapped model that mirrors #175's repair globally: if
params.promptends with an assistant message, append{ role: 'user', content: [{ type: 'text', text: 'Continue.' }] }. This eliminated the failures. Suggests the fix is to apply the existing trailing-assistant guard at the single point where the harness finalizes prompts, rather than per-path.Happy to provide redacted request dumps or test the fix.