[BUG] Desktop: error-banner "Try again" submits a new user turn (origin.kind:"human") instead of retrying the failed request

Status Open
Reported on v2.1.227
Maintainer reply None cached
Activity 1 comment · opened Aug 14, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet (closest prior art is #63530, closed as "not about Claude Code" and now locked — see below)
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

In the desktop app, when a Claude Code session dies on an API error (529 overloaded_error, rendered as "Service was busy", or a network error), the error banner offers a "Try again" button.

Clicking it does not retry the failed request. It submits a brand-new user turn into the session. The session log records it as a real human prompt:

{"type":"queue-operation","operation":"enqueue","content":"Try again"}
{"type":"queue-operation","operation":"dequeue"}
{"parentUuid":"817d667b-…","promptId":"7f7b0f94-…","type":"user",
 "message":{"role":"user","content":"Try again"},
 "origin":{"kind":"human"},"promptSource":"sdk","entrypoint":"claude-desktop",
 "permissionMode":"auto","version":"2.1.227", …}
{"type":"last-prompt","lastPrompt":"Try again","leafUuid":"cbfc3ee7-…"}

Note origin.kind: "human" and the last-prompt update — the button's label is indistinguishable from something the user typed, and it is rendered right-aligned as a user bubble.

This is not cosmetic: it corrupts the model's next turn. In the affected session the model read the injected text as user/tool output and went off investigating where an "EAGAIN"-looking string was coming from:

(assistant thinking, same session) "I'm puzzled by the repeated Try again in the log — that's the typical EAGAIN error string, so it could be coming from a network call, curl, or some underlying system command rather than the task itself."

I had a long-running reindex script attached to that session; three clicks produced three Try again user turns and one wasted investigation round-trip.

What Should Happen?

Clicking "Try again" on an API-error banner should retry the interrupted request (or at minimum re-drive the existing turn) without appending a new user message. If the design really is "re-submit something", the injected content must not be the button's own UI label, and it should be marked as client-generated rather than origin.kind: "human".

Error Messages/Logs

Preceding the injected message, ten consecutive 529s (client-side retries all exhausted), then a <synthetic> assistant turn, then the click:

system/api_error  529 {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}  req_011Ce2BHK8gArdozqs18bx27
system/api_error  529 … req_011Ce2BHvJWz1bHYFFxocvcd
system/api_error  529 … req_011Ce2BJKiBFT4tKJ5Mpc8J9
(… 7 more …)
assistant  model:"<synthetic>"  stop_reason:"stop_sequence"
queue-operation enqueue content:"Try again"     ← click
user  {"role":"user","content":"Try again"}  origin.kind:"human"

Occurrences on this machine: 3 sessions, 11 injected turns, oldest on 2.1.222 (2026-08-11), still present on 2.1.227 (2026-08-14). Triggered by both 529 overloaded_error and ECONNRESET.

Notes

The banner belongs to the front-end that renders Code sessions in the desktop app, not to the CLI: the click goes through the ordinary prompt-submission path (queue → new user turn), and the request that returned 529 is never replayed.

One detail I could not pin down, flagged as unverified: I have no explanation for why the submitted text is the literal string Try again rather than anything from the conversation, and #63530 below reports a different payload for the same click, so this may well vary by build. It doesn't affect the defect being reported — either way the click produces a new origin.kind:"human" user turn instead of a retry.

Steps to Reproduce

  1. Use a Claude Code session in the desktop app.
  2. Get the turn to die on an API error — 529 overloaded_error ("Service was busy") or a dropped connection — so the error banner with Try again appears.
  3. Click Try again.
  4. A user bubble appears at the end of the conversation and is submitted; ~/.claude/projects/<project>/<session>.jsonl gains a queue-operation enqueue + a type:"user" record with origin.kind:"human".
  5. The next assistant turn treats that text as something the user said.

Related

  • #63530 — same button, same "an old prompt appears in a new user message bubble at the end of the conversation and will submit", filed as a device-switching stale-replay bug. Closed by automation as "doesn't appear to be about Claude Code" and now locked, so re-filing here with the mechanism.

Claude Model

Opus 5 (claude-opus-5)

Is this a regression?

Not sure — observed on both 2.1.222 and 2.1.227.

Claude Code Version

2.1.227 (desktop app 1.28929.0, entrypoint claude-desktop); also seen on 2.1.222

Platform

Claude Desktop (macOS)

Operating System

macOS 27.0

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗