Background Bash tasks get lost/duplicated, turning a simple deploy into 10+ hours of retries

Status Open
Reported on v2.1.209
Maintainer reply None cached
Activity 2 comments · opened Jul 17, 2026

Bug: background Bash tasks get lost/duplicated, turning a simple deploy into 10+ hours of retries

Summary

While running vercel deploy from the Bash tool during a long session, the agent (and I, following its lead) lost track of background task IDs repeatedly: each run_in_background/auto-backgrounded invocation got a new task ID, older ones were abandoned without checking their final state, and until-loop "wait" commands used to poll a task's output file were themselves auto-backgrounded into yet another task ID — creating a chain of orphaned background processes with no single source of truth for "did the deploy finish?".

Combined with transient network errors from the sandbox reaching the Vercel API (EADDRNOTAVAIL, ETIMEDOUT, Not authorized — all on simple status-polling GETs, not on the actual build), a deploy that should take ~2 minutes stretched across 10+ hours and several separate check-ins, because there was no reliable way to answer "is anything still running, and what's its real state?"

Steps to reproduce

  1. In a long-running session, invoke a Bash command expected to take a while (e.g. vercel deploy --yes).
  2. Observe the harness auto-backgrounds it even without run_in_background: true, returning a task ID + output file path.
  3. Try to wait for it with cat <output-file> immediately — empty (not flushed yet).
  4. Try sleep N; cat <output-file> — blocked by the harness's anti-sleep-polling guard, which suggests wrapping in until ... ; do sleep 2; done.
  5. Run that until loop — it ALSO gets auto-backgrounded into a new task ID, separate from the original deploy's task ID.
  6. Now there are two background task IDs in flight for what is conceptually one operation; a task-notification eventually arrives for one of them, but the original deploy task's own completion notification can arrive separately (or the loop's completion notification is mistaken for the deploy's).
  7. Repeat under time pressure (retrying after each transient network failure) → task IDs accumulate, some abandoned, and it becomes unclear which background process (if any) is still consuming the terminal/network.

What I expected

  • A single, clearly-surfaced way to say "block here until this specific background task finishes" without the wait mechanism itself spawning another background task.
  • Or: run_in_background: false (explicit foreground) actually running in the foreground even for long-duration commands, instead of being silently promoted to background.

What happened instead

  • Foreground Bash calls with generous timeouts were still auto-backgrounded.
  • The recommended until-loop wait pattern is itself subject to the same auto-backgrounding, defeating its purpose as a "wait synchronously" idiom.
  • Net effect: several redundant vercel deploy invocations were fired across the session (because prior ones' status was unclear), each hitting fresh transient network errors, stretching what should have been a 2-minute operation across a 10+ hour, multi-check-in ordeal.

Environment

  • Claude Code (Desktop), version at time of incident: 2.1.209 (session pre-dated an in-session claude update to 2.1.212)
  • macOS, native install
  • Bash tool with run_in_background support

Suggested fix

  • Either: never auto-background a command whose caller passed run_in_background: false/omitted it with a bounded timeout, regardless of estimated duration.
  • Or: give the Bash tool a first-class "wait for task <id>" primitive that blocks the CURRENT tool call without itself becoming a new background task — so polling loops don't fork into parallel, harder-to-track background chains.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗