Repository navigation
Gemini: "Requests ending with a model turn are not supported" when a step is stored out of order (IDs are not monotonic across backward clock steps) #15073
Description
Summary
Kilo VS Code extension / CLI 7.8.8, Google provider (@ai-sdk/google, default ai-sdk runtime), gemini-3.8-flash. In the middle of a tool-calling turn a step fails with:
AI_APICallError: Requests ending with a model turn are not supported. (HTTP 400 INVALID_ARGUMENT)
isRetryable is false, so the turn hard-stops and the user has to type a new prompt (for example "continue") to resume. On a host whose wall clock steps backward (WSL2 here, but NTP corrections and VM resume do the same elsewhere) it happens several times a day: the local kilo.db holds 74 occurrences across 24 sessions.
Root cause
Identifier.create(packages/opencode/src/id/id.ts) builds IDs fromDate.now(). The "monotonic" state only handles two IDs minted in the same millisecond; nothing stops a later ID from sorting before an earlier one when the clock steps backward in between.- Parts are stored and replayed in ID order (
MessageV2.toModelMessagesEffectreadsPartTableordered byid). - A Gemini step writes its parts as
step-start > reasoning > tool. A backward step of a few hundred milliseconds betweenstep-startand the tool call stores the step astool > step-start > reasoning(ortool > step-finish > step-start > reasoningwhen the whole step was short). - The AI SDK's
convertToModelMessagesstarts a new block at everystep-start, so that message replays asassistant(tool-call) > tool(result) > assistant(reasoning). @ai-sdk/googleemits the trailing reasoning-only block as amodelturn (thought: true), and Gemini rejects any request whosecontentsend with a model turn.
Stored parts of the step right before one failure (UTC, listed in ID order, which is also time_created order):
msg_13bb9f89400124loVqN16mcfHL role=assistant finish=tool-calls
prt_13bba0cca001… 18:43:31.146 tool bash, completed <- minted before its own step-start
prt_13bba0e0a001… 18:43:31.466 step-start
prt_13bba0e0c001… 18:43:31.468 reasoning time.start=…411468 time.end=…411302 <- end is before start: the clock stepped back
prt_13bba11a6001… 18:43:32.391 step-finish reason=tool-calls
msg_13bba12cf001hH63Waabr4oSPP role=assistant error="Requests ending with a model turn are not supported." (400)
The chat UI shows the same thing: for the broken step the "Shell" block renders above its own "Reasoning" block, while every healthy step renders reasoning first.
Of the 74 stored occurrences, 72 directly follow a step whose tool part sorts before its own step-start. The remaining 2 followed an auto-compaction continuation whose summary assistant message was the last message in the replay (same wire shape, different trigger).
Over the last 3 days on this host, between 0.5 % and 1.5 % of steps for every provider in use (openai, xai, kimi, google) are stored with a tool or reasoning part ahead of the first step-start. Only Gemini fails loudly. The other providers silently receive a transcript in which the step's reasoning is replayed after its tool result.
Live confirmation
Replaying the shape above against gemini-3.8-flash through @ai-sdk/google:
control: ends with tool result [user > assistant > tool] -> 200
misordered replay, unguarded [user > assistant > tool > assistant] -> 400 Requests ending with a model turn are not supported.
misordered replay, guarded [user > assistant > tool] -> 200 (trailing reasoning-only assistant dropped)
text tail, unguarded [user > assistant] -> 400 Requests ending with a model turn are not supported.
text tail, guarded [user > assistant > user] -> 200 ("Continue." primed)
Related upstream reports
- Requests ending with a model turn are not supported anomalyco/opencode#45359 and gemini-3.8-flash: 400 'Requests ending with a model turn are not supported' after a model turn anomalyco/opencode#47034 report the same error. Upstream traced one trigger to the max-steps assistant prefill (Kilo already sends
MAX_STEPS_PROMPTas a user turn) and fix(provider): keep Gemini requests from ending with a model turn anomalyco/opencode#55382 primes a user turn for Gemini on the v1 line. Neither covers the out-of-order part replay, which is what produces the error here.
Fix
Two layers, in the linked PR:
Identifier.createkeeps wall-clock IDs strictly ascending across a backward clock step, so new steps can no longer be stored out of order.ProviderTransform.messagenever lets a Gemini request end on a model turn: a trailing reasoning-only assistant message is dropped and any other assistant tail gets a primed user turn. Outbound only, so sessions that already contain a misordered step (and the compaction-continuation trigger) recover without touching the stored transcript.
Not covered: messages are ordered by time_created and that column is still the raw wall clock, so a backward step can still reorder whole messages (each still ends on a tool result, so Gemini accepts it). A repair for already-stored misordered steps on replay is also possible but left out of the fix.
Activity
piercypixel commentedon Oct 14, 2026
Filed upstream, where the shared files live: issue anomalyco/opencode#55514 and PR anomalyco/opencode#55515 against
v1. Closed #15074 to avoid carrying akilocode_changecopy. Once the upstream PR merges, the next upstream merge intopackages/opencodepicks it up and this issue can be closed. Branchpiercypixel/kilocode:fix/monotonic-ids-gemini-model-turnstill holds the port if it is wanted sooner.