Skip to content

[Bug]: Antigravity + Claude permanently bricks thread after steer/resume with raw thinking.signature: Field required as completed assistant_message #28870

Open

Description

@jamesdchen

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Start (or hand off to) a thread on the Antigravity provider using an extended-thinking Claude model (claude-opus-5-5).
  2. Run a multi-step turn (turn:1) that emits thinking (reasoning) blocks and tool calls — for example, a turn where Antigravity sets an internal schedule wake timer that keeps turn:1 open in the background after posting an interim assistant message.
  3. While turn:1 is still open, send a follow-up message so it is promoted to a steer (inputIntent: "promoted_queued_to_steer"), causing the Antigravity ACP turn/process to terminate after ~16s (as in [Bug]: Steer on an Antigravity thread kills the turn (interruptTurn fails, then AcpProcessExitedError) #19689) and session/resume from file storage (AGY_ACP_FORCE_FILE_STORAGE=1) for turn:2.
  4. Send another normal message (turn:3, inputIntent: "turn_start").

Expected behavior

  1. Resuming or steering an Antigravity + Claude session preserves thinking.signature on historical thinking blocks (or strips/redacts unsigned thinking blocks when reconstructing messages), so turn:2 and later turns succeed.
  2. When Vertex/Anthropic returns an HTTP 400 invalid_request_error payload ({"type":"error","error":{"type":"invalid_request_error",...}}), AntigravityAdapterV2 fails the turn with a structured error timeline item instead of recording the raw JSON string as a completed assistant_message.
  3. If a native Antigravity session fails with thinking.signature: Field required, T3 Code invalidates/rotates the poisoned providerThreadId (via context handoff) rather than routing every future turn into a permanently broken session.

Actual behavior

  1. Within turn:1, all 17 internal tool-call rounds succeed (19:50:39Z–19:53:52Z) while the ACP process holds the conversation state in memory.
  2. At 19:53:52Z, the assistant emits an interim status message, while an internal Antigravity schedule timer (not surfaced as a T3 timeline tool item) holds turn:1 open in the background.
  3. When a user message arrives at 19:54:39.357Z (inputIntent: "promoted_queued_to_steer"), turn:1 terminates 16.08s later at 19:54:55.435Z (matching the interruptTurn timeout / AcpProcessExitedError behavior in [Bug]: Steer on an Antigravity thread kills the turn (interruptTurn fails, then AcpProcessExitedError) #19689).
  4. After cold-starting/resuming the session (19:57:23.175Z, turn:2), Vertex Claude rejects the request because messages[1].content[0].thinking (the very first assistant thinking block from turn:1) is missing its required signature field:
    {"type":"error","error":{"type":"invalid_request_error","message":"messages.1.content.0.thinking.signature: Field required"},"request_id":"req_vrtx_011CgcoGLsLVvNgybmeJxixN"}
  5. Antigravity emits that escaped JSON error payload as "type": "assistant_message" with "status": "completed", followed by a normal checkpoint (same ACP error-surfacing gap as Antigravity quota exhaustion (HTTP 429) finishes the turn as completed instead of showing the usage-limit banner #28658).
  6. Because messages[1] is permanently at the head of that native Antigravity session's persisted history and the run ends completed, every subsequent turn (turn:3, etc.) reuses the same poisoned providerThreadId and fails with the exact same raw JSON assistant_message, permanently bricking the thread.

(Side note from the same trace: during the claudeAgent -> antigravity full_thread_summary handoff right before turn:1, the handoff summary stopped at the first usage_limit error in run 182 and omitted runs 183–187 containing 5 subagent failure notification items, leaving the target provider unaware that the prior subagents had failed until it manually paginated t3_thread_read.)

Impact

Blocks work completely

Version or commit

t3 v0.1.6 (managed antigravity-acp with AGY_ACP_FORCE_FILE_STORAGE=1)

Environment

Linux host environment + Windows 11 client (T3 Code web/desktop), Provider: Antigravity (ACP), Model: claude-opus-5-5 (after provider handoff from claudeAgent claude-opus-5-5)

Logs or stack traces

// Sanitized timeline items from exported thread JSONL (runs 188-190):

// turn:1 first thinking block (succeeded across 17 tool rounds inside turn:1, later missing signature on turn:2/turn:3):
{
  "id": "turn-item:provider:antigravity:native-item:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A1%3Areasoning%3A0",
  "runId": "run:thread:<thread-id>:ordinal:188",
  "providerThreadId": "provider-thread:provider:antigravity:native-thread:pending%3Arun%3Athread%3A<thread-id>%3Aordinal%3A188",
  "providerTurnId": "provider-turn:provider:antigravity:native-turn:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A1",
  "ordinal": 188000003,
  "status": "completed",
  "startedAt": "2026-11-01T19:50:39.912Z",
  "completedAt": "2026-11-01T19:50:45.785Z",
  "type": "reasoning"
}

// turn:1 interim assistant message (held open by background schedule timer until steer arrives at 19:54:39.357Z -> ends 16.08s later at 19:54:55.435Z):
{
  "id": "turn-item:provider:antigravity:native-item:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A1%3Aassistant%3A0",
  "runId": "run:thread:<thread-id>:ordinal:188",
  "ordinal": 188000040,
  "status": "completed",
  "startedAt": "2026-11-01T19:53:52.705Z",
  "completedAt": "2026-11-01T19:54:55.435Z",
  "type": "assistant_message"
}

// User message promoted to steer while turn:1 was open:
{
  "runId": "run:thread:<thread-id>:ordinal:188",
  "nodeId": "node:run:run%3Athread%3A<thread-id>%3Aordinal%3A188:attempt:2:root",
  "ordinal": 188000041,
  "status": "completed",
  "startedAt": "2026-11-01T19:54:39.357Z",
  "type": "user_message",
  "inputIntent": "promoted_queued_to_steer",
  "text": "where are all of the subagents?"
}

// turn:2 fails after resume with missing thinking.signature, recorded as a completed assistant_message:
{
  "id": "turn-item:provider:antigravity:native-item:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A2%3Aassistant%3A0",
  "runId": "run:thread:<thread-id>:ordinal:188",
  "providerTurnId": "provider-turn:provider:antigravity:native-turn:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A2",
  "ordinal": 188000042,
  "status": "completed",
  "startedAt": "2026-11-01T19:57:23.175Z",
  "completedAt": "2026-11-01T19:57:23.201Z",
  "type": "assistant_message",
  "text": "{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages.1.content.0.thinking.signature: Field required\"},\"request_id\":\"req_vrtx_011CgcoGLsLVvNgybmeJxixN\"}",
  "streaming": false
}

// turn:3 ("what happened?") on run ordinal 190 hits the exact same error 24s later because providerThreadId is permanently poisoned:
{
  "id": "turn-item:provider:antigravity:native-item:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A3%3Aassistant%3A0",
  "runId": "run:thread:<thread-id>:ordinal:190",
  "providerTurnId": "provider-turn:provider:antigravity:native-turn:provider-instance%3Aantigravity%3A<session-id>%3Aturn%3A3",
  "ordinal": 190000002,
  "status": "completed",
  "startedAt": "2026-11-01T19:58:30.772Z",
  "completedAt": "2026-11-01T19:58:30.794Z",
  "type": "assistant_message",
  "text": "{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages.1.content.0.thinking.signature: Field required\"},\"request_id\":\"req_vrtx_011CgcoMLAKCNDWNgMm4eKVd\"}",
  "streaming": false
}

Related issues:

Workaround

Switch the thread to a different provider (e.g., back to Claude) or switch models/providers for one turn so T3 Code allocates a fresh providerThreadId via context handoff instead of reusing the poisoned Antigravity session. Avoid using Steer while an Antigravity + Claude turn is open.

Activity

  1. jamesdchen commented on Nov 1, 2026

    @jamesdchen
    Author

    Follow-up from the same session (request id req_vrtx_011CgcoGLsLVvNgybmeJxixN).

    The signature is never written, not stripped after the fact. In that Antigravity conversation the 17 planner steps have thinking text and thinking_signature length 0. Gemini sessions on the same install do store thinking_signature. The in-memory tool loop of the first turn succeeds. The next user turn replays from the database and Vertex rejects messages.1.content.0.thinking.signature.

    So this is not only steer/resume. Any second Claude turn that emitted thinking hits it. Rotating to a fresh native session (as in #28889) avoids the brick. Continuing the same native session needs the signature kept on the Gemini thought part and put back on replay. A local proxy reinjection for that is in progress and was not live-verified: the Claude & GPT 5-hour quota was exhausted before a high-thinking second turn.

  2. izahai commented on Nov 5, 2026

    @izahai

    I reproduced this live against the managed runtime (antigravity-acp 1.4.1, claude-opus-5-5-high, AGY_ACP_FORCE_FILE_STORAGE=1) with a standalone ACP client that sends the same calls T3 sends (clientInfo: zed, oauth-personal, session/resume). The runtime does write the signature to disk. session/resume and session/load remove it.

    What breaks the session is a runtime restart, not a particular kind of turn. In my case the T3 desktop app restarted about 9 s after the first turn finished (update to 0.1.7). The next message started a new runtime and called session/resume, and every turn after that failed with messages.1.content.0.thinking.signature: Field required.

    Repro (no T3 UI involved)

    Step ACP calls Signature in conversations/<id>.db* Result
    Control session/new → prompt (thinking) → prompt, same process present turn 2 OK
    1 session/new → prompt (thinking) → SIGKILL the runtime present —
    2 new runtime → session/resume (no prompt) gone —
    3 prompt gone thinking.signature: Field required (req_vrtx_011CgiyuUD5RsvEqUXn69Myv)
    Alt new runtime → session/load → prompt gone same error (req_vrtx_011CgiyqNWAfcqRv4XjaZ4CB)

    * The planner step (steps.step_type = 15) stores the thinking text at payload field 20.3 and the signature at 20.14. Gemini planner steps use 20.14 as well. After resume or load, the runtime rewrites the step with 20.3 intact and 20.14 missing, so the data is lost for good. Restarting again can't bring it back.

    Step 2 alone is enough. Resuming without sending a prompt already rewrites the step without the signature.

    Repro script (Node + Python, no dependencies): https://gist.github.com/izahai/60a69e79e03e351e18ad4befb8900f3e

    What this means for #28889

    • It reproduces every time. Any Claude session on Antigravity whose history has a thinking block breaks on its first session/resume or session/load. That covers app updates and restarts, idle reaping, steer timeouts ([Bug]: Steer on an Antigravity thread kills the turn (interruptTurn fails, then AcpProcessExitedError) #19689), and provider sign-out.
    • Rotating reactively after the error (the current PR) recovers the thread but always costs one failed turn. T3 already knows it is resuming. It could rotate before resuming instead: if the native history holds a Claude thinking step, start the fresh session with a context handoff and skip the doomed resume. The proper fix still belongs in the runtime: keep 20.14 when it loads a step.

    Investigated with Claude Opus 5.5.

  3. schneidervvv commented on Nov 5, 2026

    @schneidervvv

    Live reproduction on 0.1.8-nightly.20261104.4192 (7f6f47b27b44456f1c8214d3b566b375c09f629e) confirming both the session/resume signature stripping on delegated-subagent wakeup and the subsequent session/new -> session/load retry loop before #28889.

    Environment

    • Desktop client: 0.1.7-nightly.20261104.4151 (macOS darwin arm64, Kernel 27.0.0)
    • Server: 0.1.8-nightly.20261104.4192 (7f6f47b27b44456f1c8214d3b566b375c09f629e), Node v24.22.1
    • Provider / Model: Managed Antigravity ACP 1.4.1, claude-opus-5-5-high

    What happened & timeline

    1. Turns 1–3 (05:46:29Z–05:52:57Z): Parent thread (b8219a14-..., native session fa686dee-...) ran 3 turns on claude-opus-5-5-high (including a steering_restart on Turn 3 attempt 2 at 05:51:59Z) and delegated 3 child threads (041e4791-..., 47707934-..., c9071a90-...).
    2. Child threads vs. parent thread SQLite state:
      • All 3 child threads ran to completion inside their initial session/new runtime without ever calling session/resume or session/load. In their <session>.db files, every planner step (step_type = 15, field 20) still retains both 20.3 (thinking) and 20.14 (thinking_signature, CAQS...).
      • In the parent thread's fa686dee-...db, all 25 thinking steps have 20.3 (thinking) intact and 20.14 (thinking_signature) stripped after resume/load.
    3. Run 5 (06:28:51Z) — Subagent callback triggers cold session/resume:
      • ~36 minutes after Turn 3 completed, a delegated child thread finished and woke the parent thread.
      • T3 spawned a new ACP runtime and called initialize -> authenticate -> session/resume (06:28:54.250Z) -> session/set_config_option -> session/prompt (06:28:56.712Z).
      • Vertex AI rejected the prompt with 400 invalid_request_error: messages.1.content.0.thinking.signature: Field required (req_vrtx_011CgjJrXHzg5WdFd8vZrPfm), recorded at steps.idx = 67 (step_type = 17).
      • AntigravityTurnOutcome.ts (turnFailure, lines 95–127) read step_type = 17 and failed Run 5 (status = "failed"), flagging the adapter to restart its runtime before the next turn.
    4. Run 6 (06:31:24Z) — continue falls back to session/new + session/load on the same poisoned session:
      • On the next user prompt (continue), AcpAdapterV2 restarted the runtime (restartRuntimeAfterTeardownIfRequired), which ran initialize -> authenticate -> session/new (06:31:29.158Z), and then activateSession (packages/provider-acp/src/server/adapter.ts:7061-7084) saw canLoadSession === true and called session/load (06:31:30.248Z) on the same fa686dee-... native session.
      • session/prompt (06:31:32.138Z) failed again with messages.1.content.0.thinking.signature: Field required (req_vrtx_011CgjK3xj23rcPGVDgP4apf, steps.idx = 69, step_type = 17).

    Evidence (logs/provider/events.<thread>.log)

    [2026-11-05T06:28:54.250Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/resume","status":"started"}}
    [2026-11-05T06:28:55.551Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/resume","status":"succeeded"}}
    [2026-11-05T06:28:56.712Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/prompt","status":"started"}}
    [2026-11-05T06:28:58.339Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/prompt","status":"succeeded"}}
    [2026-11-05T06:31:25.044Z] {"kind":"request","provider":"antigravity","payload":{"method":"initialize","status":"started"}}
    [2026-11-05T06:31:29.158Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/new","status":"started"}}
    [2026-11-05T06:31:30.248Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/load","status":"started"}}
    [2026-11-05T06:31:31.196Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/load","status":"succeeded"}}
    [2026-11-05T06:31:32.138Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/prompt","status":"started"}}
    [2026-11-05T06:31:33.504Z] {"kind":"request","provider":"antigravity","payload":{"method":"session/prompt","status":"succeeded"}}
    

    Triaged with Antigravity (gemini-4-argon-medium).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions