[Bug] Random text insertion in agent harness under high concurrent load (20+ agents)

Status Fixed / completed
Reported on v2.1.183
Maintainer reply None cached
Activity 11 comments · opened Jun 21, 2026 · closed Jul 21, 2026

Bug Description
Issue: Random "hello" text insertions in agent harness when running 20+ Claude Code Terminal CLI agents simultaneously on Mac Details: • Occurs consistently when running more than 20 agents concurrently • Below 20 agents, everything works fine • Random "hello" strings appear inserted into the main agent harness • Ruled out tmux and external causes • Only happens under high agent load • Agents otherwise function correctly, but the crosstalk is concerning Environment: Claude Code Terminal CLI (not SDK or direct API calls), macOS Reproducibility: Consistently replicable at 20+ concurrent agents This appears to be a multi-agent isolation or resource contention issue that becomes apparent at scale.

Environment Info

  • Platform: darwin
  • Terminal: vscode
  • Version: 2.1.183
  • Feedback ID: 86d357f7-e17d-41e4-926a-2614fffc1e3c

Errors

[]

View original on GitHub ↗

11 Comments

github-actions[bot] · 2 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/66020
  2. https://github.com/anthropics/claude-code/issues/62630
  3. https://github.com/anthropics/claude-code/issues/48811

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

falconleon · 2 months ago

Updated symptom

  • The injected text is a clean literal token (hello) that appears in my single foreground/main session — as if it had been typed at the input prompt. It is not garbled/scrambled output; it's well-formed text landing in the wrong place.
  • It has now recurred randomly over several hours in that one main session, specifically under 20+ concurrent Claude Code CLI agents on macOS (CLI, not SDK).
  • Environment: macOS, Claude Code 2.1.183, agents driven by a tmux-based multi-agent orchestrator.

I ruled out my own tooling as the emitter

I grepped my entire orchestration stack (daemon, tmux send paths, hooks, skills, test harness) for anything that writes the literal string hello into a pane. There is none — every pane-write my tooling does is a distinctively-templated string (e.g. New message from @<sender> ...). If my tooling had misrouted text into the main session, I'd see that template, not hello. So a clean literal hello is coming from the harness/terminal layer, not my orchestration.

The three suggested duplicates are different bugs

  • #66020 — macOS kernel zone leak (data.kalloc.1024) → kernel panic. A resource/kernel crash, not text insertion. (Related to my setup only as a separate stability risk; see I/O note below.)
  • #62630isolation:"worktree" bases worktrees on origin/HEAD vs HEAD. Git base-ref selection; unrelated.
  • #48811isolation:"worktree" silently ignored (worktreePath:"null"). Worktree creation failure; unrelated.

They share only the area:agents / platform:macos / "concurrent agents" labels — not the symptom.

Genuinely-related issues (cross-session text bleed)

These describe the actual mechanism — text from one session/agent surfacing in another session's input/output:

  • #68465 — background session's output appeared verbatim in another session's input stream, attributed to the daemon multiplexer. (Reported on Windows; shared daemon code.) Closest match.
  • #64651 — VSCode: background-agent output streams into the foreground chat under multiple background agents.
  • #23919 — macOS: typeahead/autocomplete text leaked between concurrent sessions' input boxes.
  • #39027 / #29233 — background task-notification materialized as a synthetic role:user turn; phantom text appears "as if typed," and scales with concurrent background-agent completions.

Could this be triaged against that set rather than the three above?

Possible exacerbator: file-I/O pressure

My ~/.claude is large (~3.8 GB; ~4,800 session transcripts), so every agent turn does substantial file I/O (transcript reads/writes, shell-snapshot sourcing). The cross-session bleed appears timing-sensitive — it only shows up under heavy concurrent load. Is the input-routing path sensitive to I/O/scheduler pressure? If helpful I can capture timestamped pane snapshots correlating detections with load/I/O.

Please keep this open — it's a reproducible, recurring cross-session input-bleed, distinct from the three flagged issues.

falconleon · 2 months ago

I have multiple environments exhibiting this if you want to examine them. reach out via leon at letto dot ca if you would like to.

kcarriedo · 2 months ago

The "hello" crosstalk at 20+ concurrent agents points to a shared TTY or file-descriptor leak -- something is mixing the stdio streams of parallel agent processes at a layer below the individual agent logic.

A few things worth ruling out:

  1. Shared stdin/stdout without proper isolation. When you spawn 20+ agents via Claude Code Terminal CLI, check whether the parent process is inheriting file descriptors into child processes without setting FD_CLOEXEC. If file descriptors are inherited across forks, writes from one agent's stdout can land in another agent's input buffer at high concurrency.
  1. A named pipe or socket being reused across agent processes. The "hello" string appearing in the harness (not in agent output) suggests it is coming from a coordination or keepalive path -- something like a health-check or idle notification that normally goes to one endpoint but is mis-routed under load.
  1. Process group isolation. If agents are not in their own process groups, a signal or write from one can affect the whole group's terminal state.

A useful diagnostic: run at 20+ concurrent agents with strace on the harness process (or dtrace on macOS) and capture all write() calls on file descriptors 0-3. That should show whether the "hello" bytes originate inside the harness or are incoming from a child. The fact that it disappears below 20 agents suggests a race condition with a threshold -- probably a buffer or queue that overflows and starts cross-writing when concurrency crosses that level.

Has the insertion been reproducible with a specific agent count consistently (always at exactly 20+) or does it vary slightly run to run?

falconleon · 2 months ago

Update from ~2 days of continuous monitoring (a read-only watcher capturing pane state + per-event concurrency). This sharpens the repro and answers the threshold question.

Captured: 41 genuine injection events on Claude Code 2.1.187 (filed against 2.1.183 — still present).

Concurrency threshold is ~12, not 20. Zero genuine injections occurred below 12 concurrent claude processes; every event clustered at 12–14. So the earlier "20+" was an overestimate — the floor is lower and fairly sharp, which is consistent with a buffer/queue that starts cross-writing once concurrency crosses a threshold.

Always the same single session. Every one of the 41 events landed in one session (the one I interact with most) and never in any other concurrent session. The target is stable, not random across sessions.

Two shapes — and the second is the diagnostic one:

  1. A bare ❯ hello appears as a standalone submitted prompt.
  2. hello is appended to the tail of an in-progress input line — e.g. a real message of mine ending up as …ones that were created. hello.

Shape (2) is the key signal: the stray token is glued onto the existing input buffer of the live session, not delivered as a separate line. That points at an input-buffer / file-descriptor race appending bytes to the active session's stdin, rather than a fresh notification or a render artifact — which lines up with @kcarriedo's FD-inheritance / keepalive-misroute hypothesis above.

Cadence: bursty — e.g. 9 events in ~7 minutes at a stable 12-process plateau, sometimes ~1/minute over 10–60 minute windows.

falconleon · 2 months ago

Follow-up after an extended instrumented investigation: reproduction sharpened, and every external cause exhaustively ruled out.

Still reproducing

  • Present on Claude Code 2.1.191 (filed against 2.1.183) — persisted across versions.
  • Persists across a full environment reset (clean binary reinstall + daemon restart).
  • A bare hello appears as a submitted user turn in one specific session under high concurrent multi-agent load; always the same session.

What the transcript shows (key new evidence) — the injected turns are recorded as promptSource: "typed", origin: {"kind":"human"}, userType: "external" — byte-for-byte identical to my real typed messages, with no isMeta / bypassPermissions / synthetic markers. So they are not the background-task synthetic-turn class (#39027/#29233); they fully masquerade as keyboard input.

Reproduction conditions (refined)

  • Concurrency threshold ≈ 12 concurrent claude processes — not 20. Across ~40+ events, zero below 12; all 12–14.
  • Bursty (e.g. 9 in ~7 min); fires even when I'm not at the keyboard.

Exhaustive elimination of external injectors

  1. Terminal/keyboard — a live recurrence happened with no writable terminal client attached (tmux list-clients showed only a read-only mirror).
  2. VS Code — occurs with it fully closed; the apparent "VS Code attach" was a read-only mirror that merely inherited TERM_PROGRAM=vscode and cannot inject.
  3. Voice dictation (Wispr) — ruled out.
  4. My multi-agent orchestrator (tmux-based daemon) — correlated all event timestamps against its message store, queue, nudge dispatch, and logs: zero hello in any send path; its pane-writes only carry fixed templated text.
  5. The web GUI (deterministic React app) — no hello literal in any send path, no default/draft, no auto-resend; only writes to a pane on explicit composer submit, and hello never appears in the composer. Being connected is incidental.

What that leaves — every external sender eliminated, yet CC records a typed/human turn that no external process produced, tightly correlated with concurrent-session count → the remaining explanation is internal to CC's input pipeline (a cross-session input-bleed mimicking typed input, distinct from the task-notification path).

Related: genuinely #68465 / #23919 / #64651 / #39027/#29233 (cross-session input bleed). The three bot-flagged dups (#66020 kernel leak; #62630/#48811 worktree) are unrelated.

Can provide: sanitized JSONL excerpts (phantom vs. real typed turn), per-event concurrency, repro env; can't attempt dtrace/fs_usage (SIP-limited).

falconleon · 2 months ago

Any help in fixing/mitigating this would be appreciated.

falconleon · 2 months ago

This is so annoying:
❯ if so - gihello

✶ Grooving… (23s · ↓ 2.9k tokens · thinking more with medium effort)

❯ if so - give me the hello
❯ message to relay

the hello's are randomly inserted.

falconleon · 2 months ago
The "hello" crosstalk at 20+ concurrent agents points to a shared TTY or file-descriptor leak -- something is mixing the stdio streams of parallel agent processes at a layer below the individual agent logic. A few things worth ruling out: 1. Shared stdin/stdout without proper isolation. When you spawn 20+ agents via Claude Code Terminal CLI, check whether the parent process is inheriting file descriptors into child processes without setting FD_CLOEXEC. If file descriptors are inherited across forks, writes from one agent's stdout can land in another agent's input buffer at high concurrency. 2. A named pipe or socket being reused across agent processes. The "hello" string appearing in the harness (not in agent output) suggests it is coming from a coordination or keepalive path -- something like a health-check or idle notification that normally goes to one endpoint but is mis-routed under load. 3. Process group isolation. If agents are not in their own process groups, a signal or write from one can affect the whole group's terminal state. A useful diagnostic: run at 20+ concurrent agents with strace on the harness process (or dtrace on macOS) and capture all write() calls on file descriptors 0-3. That should show whether the "hello" bytes originate inside the harness or are incoming from a child. The fact that it disappears below 20 agents suggests a race condition with a threshold -- probably a buffer or queue that overflows and starts cross-writing when concurrency crosses that level. Has the insertion been reproducible with a specific agent count consistently (always at exactly 20+) or does it vary slightly run to run?

Anything new on this?

falconleon · 1 month ago

@kcarriedo I have updated to 2.1.201 and it looks like this has been mitigated? I haven't see a random hello since upgrading. Its great news.

Any comment? If this was intentional then we can call this ticket closed.

Edit - its back at 20+ agents. still causing problems although at higher concurrency

Leon

falconleon · 1 month ago

OK I found the source. My Project https://thrum.team/ has ~10,900 Go test functions + ~1,150 Vitest tests + a separate ~100-250 scenario E2E harness.
I found it in one test. :( :(
Closing now.