Skip to content

Gemini 400 "Requests ending with a model turn are not supported" when a step is stored out of order: Identifier.create is not monotonic across backward clock steps #55514

Closed as not planned

Description

@piercypixel

Description

Google provider (@ai-sdk/google), gemini-3.8-flash, v1 line (seen through Kilo 7.8.8, which ships the v1 packages/opencode unchanged in the relevant files). Mid-way through a tool-calling turn a step fails with:

AI_APICallError: Requests ending with a model turn are not supported.   (400 INVALID_ARGUMENT)

Not retryable, so the turn stops until a new prompt is typed. Same error as #45359 / #47034, but a different trigger from the max-steps prefill, and #55382 alone does not cover it.

Root cause

  1. Identifier.create (packages/opencode/src/id/id.ts) takes Date.now() and only handles two IDs in the same millisecond. When the wall clock steps backward between two parts of one step, the later part gets a smaller ID. Clocks do step backward: NTP corrections, VM resume, and WSL2 (where this box steps by seconds every few seconds).
  2. Parts are replayed in ID order (toModelMessagesEffect reads PartTable ordered by id).
  3. A Gemini step writes step-start > reasoning > tool. With a backward step in between it is stored as tool > step-start > reasoning (or tool > step-finish > step-start > reasoning).
  4. convertToModelMessages opens a new block at every step-start, so the message replays as assistant(tool-call) > tool(result) > assistant(reasoning).
  5. @ai-sdk/google emits that trailing reasoning-only block as a model turn with thought: true, and Gemini rejects contents that end on a model turn.

Stored parts of the step right before one failure (UTC, in ID order):

msg_13bb9f89400124loVqN16mcfHL  assistant, finish=tool-calls
  prt_13bba0cca001…  18:43:31.146  tool (bash, completed)   <- 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 before start
  prt_13bba11a6001…  18:43:32.391  step-finish
msg_13bba12cf001hH63Waabr4oSPP  assistant, error "Requests ending with a model turn are not supported."

In one local database: 74 occurrences across 24 sessions; 72 directly follow a step stored like the one above, the other 2 follow an auto-compaction continuation whose summary assistant message was last. Over three days, 0.5–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 rejects it; the others silently get the reasoning replayed after the tool result.

Replaying that shape against gemini-3.8-flash directly: [user, assistant(tool-call), tool(result)] is accepted, adding the trailing assistant(reasoning) gives the 400, dropping it again gives 200.

V2

packages/schema/src/identifier.ts on dev has the same lastTimestamp/counter logic, so IDs can still go backward there. V2 orders history by a seq column, so I have not shown the replay symptom on dev; I only verified v1.

Fix

PR against v1 follows: make Identifier.create strictly ascending across a backward step, and have ProviderTransform.message drop a trailing reasoning-only assistant message for the Gemini SDKs and prime a user turn behind any other assistant tail (outbound only). Kilo tracks this in Kilo-Org/kilocode#15073 and will pull the fix once it lands here.

OpenCode version

v1 at a95d9c0 (2026-10-14); first seen on Kilo 7.8.8.

Operating System

Linux (WSL2)

Activity

  1. opencode-agent commented on Oct 14, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed root-cause analysis and the stored-part dump, @piercypixel.

    This report is about the v1 line (0.x/1.x). v1 now gets fixes only for critical bugs: data loss, security problems, or crashes and breakage with no workaround. This bug is a recoverable 400 that sending a new prompt gets past, so it is unlikely to be fixed on v1. We recommend upgrading to v2 (@opencode/cli), which is where active development happens.

    As you noted, packages/schema/src/identifier.ts on v2 has the same lastTimestamp/counter logic, so IDs can still go backward after a clock step. However, v2 orders history by seq, and the replay failure has not been shown there. If you see this error on v2, or you think it should count as critical, please reply here with the v2 version and details.

    Related issues and PRs:

  2. opencode-agent commented on Oct 15, 2026

    @opencode-agent
    Contributor

    Closing as not planned. This bug is in v1, which only gets critical fixes. The Gemini 400 that follows a clock step backward is a recoverable error: sending a new prompt continues the turn. We kept the issue open for a day in case it also shows up on v2 or turned out to be critical. Nothing came in to show either.

    Thank you for the detailed root-cause analysis. If you see the same failure on v2 (@opencode/cli), please open a new issue with the v2 version and the stored part order, and link back to this one. #55382 is still open for the related Gemini assistant-tail cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions