Skip to content

[Bug]: Claude provider re-sends each user message as a second, concurrent turn #13275

Description

@ferran9908

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. Open a thread with the Claude provider (claudeAgent, model claude-opus-5-5, runtime mode full-access).
  2. Send a first message. It gets one turn, as expected.
  3. Send a follow-up message that starts a long turn (many tool calls, e.g. MCP design-tool edits).
  4. Wait 20–50 seconds while that turn is still running.

I don't have a minimal deterministic repro yet. In the thread below it happened on 6 of 7 user messages (every message after the first).

Expected behavior

One user message → one thread.turn-start-requested → one provider turn.

Actual behavior

About 18–52 s after each user message, the server starts a second provider turn with a new turn id and sends the same user message text into the same Claude session again. Nothing in the UI shows it was sent twice. The first turn is often still running, so two agents run the same prompt at the same time.

Evidence from one thread (91719899-32ae-46d9-aad0-962d9e216e9e):

  • orchestration_events has 7 thread.turn-start-requested events, but projection_turns has 13 turns. The 6 extra turns have pending_message_id = NULL.
  • The Claude session transcript (~/.claude/projects/.../<session>.jsonl) has each user prompt written twice, e.g. identical text at 14:45:29.478Z and 14:46:06.429Z, and at 15:05:45.217Z and 15:06:03.925Z. Each write has its own queue-operation enqueue/dequeue pair.
  • The provider event log shows a fresh turn.started + claude/command_lifecycle (queued → started) with a new command_uuid for the duplicate, followed by session.configured, while the original command has not yet reached completed.
User message (requested_at) Original turn Duplicate turn started Overlap
14:26:19 efeb9433… (done 14:27:09) 14:27:11 (e23bf5b9…) no, back-to-back
14:45:29 b2965c7d… (done 14:46:33) 14:46:06 (bb43102b…) yes
14:51:59 ad7469d9… (done 14:52:42) 14:52:23 (3edebbd1…) yes
15:02:29 6150906b… (done 15:02:49) 15:02:54 (5007c960…) no
15:05:45 51f6c9d6… (done 15:07:08) 15:06:03 (767e66ac…) yes, ~65 s
15:31:22 55fdedfc… (done 15:31:45) 15:32:18 (0376de9f…) no

Consequences:

  • Duplicate, often contradictory assistant answers appear interleaved in the thread.
  • When the turns overlap, both agents act on the same external state. In my case both edited the same design file through an MCP server and overwrote each other's work. Each agent saw the other as an unknown "other session".
  • Tokens and cost are doubled.

It happened again in a second, separate thread the same day: a follow-up message spawned a twin run that rewrote the same files the first run was editing.

Impact

Major degradation or frequent failure

Version or commit

T3 Code (Nightly) 0.0.43-nightly.20260921.2058

Environment

macOS (Darwin 25.4.0), desktop app, service-managed server. Provider: Claude Agent SDK (claudeAgent), model claude-opus-5-5, fast mode off, runtime mode full-access.

Logs or stack traces

# orchestration_events vs projection_turns for the thread
thread.turn-start-requested | 7
projection_turns            | 13   (6 with pending_message_id NULL)

# provider log: duplicate turn for the 14:45:29 message
[14:45:29.433Z] CANON turn.started turnId=b2965c7d-...
[14:45:29.445Z] NTIVE claude/command_lifecycle command_uuid=b2965c7d-... state=queued
[14:45:29.449Z] NTIVE claude/command_lifecycle command_uuid=b2965c7d-... state=started
[14:46:06.387Z] CANON turn.started turnId=bb43102b-...          <-- no matching turn-start-requested
[14:46:06.392Z] NTIVE claude/command_lifecycle command_uuid=bb43102b-... state=queued
[14:46:06.396Z] NTIVE claude/command_lifecycle command_uuid=bb43102b-... state=started
[14:46:06.444Z] CANON session.configured turnId=bb43102b-...
[14:46:33.056Z] NTIVE claude/command_lifecycle command_uuid=b2965c7d-... state=completed

Full provider event logs for the thread (~24 MB) are available if useful.

Workaround

None found. Waiting for the thread to show a single finished response before sending the next message doesn't prevent it, because the duplicate is created server-side 20–50 s after a single send.

Activity

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

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions