pingdotgg / pingdotgg/t3code

[Bug]: Claude session exits when a background Bash task stops after its turn completed

Open
#9,698 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
23k
Forks
5.9k
Avg merge
11h 14m
Merged PRs (30d)
357

Description

Before submitting
  • I searched existing issues and did not find a duplicate.
  • I added enough detail to help find the cause.
Area

apps/server

Steps to reproduce
  1. Start a Claude thread in the desktop app with full access.
  2. Ask Claude to start a long Bash command with run_in_background: true and timeout: 600000.
  3. Let the foreground turn finish while the Bash task keeps running.
  4. Wait for the Bash task to end as failed or killed.

I saw this twice with a Bash task that started a child process and waited for it. I have not reduced it to a short command yet.

The tasks stopped before their declared ten-minute timeout. One ran for about five minutes and forty-two seconds. The other ran for about seven minutes and fourteen seconds.

Expected behavior

T3 should mark the background task as failed or cancelled. The Claude session should stay ready, or restart on the next message.

A failed background command should not end the provider session. The foreground turn had already completed.

Actual behavior

T3 receives the background task's stopped and failed events. Less than one second later, it emits Claude runtime stream failed. and closes the Claude session.

The foreground Claude turn had completed successfully several minutes earlier. The same long job does not use this Claude adapter path when Codex owns the thread.

Impact

Major degradation or frequent failure

Long background jobs can die without their requested timeout being reached. The thread then shows a provider error and needs a new Claude session.

Version or commit

T3 Code 0.0.38

Environment

macOS 26.6.2, build 25G83, Apple Silicon, T3 Code desktop 0.0.38, Claude Code 2.1.260, Claude Opus 5 with the one-million-token context option, full-access runtime.

Logs or stack traces
# First occurrence
12:06:57  claude/result/success, foreground turn completed
12:12:34  claude/system/task_notification, status: stopped
12:12:34  claude/system/task_updated, status: failed
12:12:35  runtime.error, message: "Claude runtime stream failed."
             failureTags: ["ProviderAdapterProcessError"]
12:12:35  session.exited, reason: "Session stopped", exitKind: "graceful"

# Second occurrence
13:50:41  claude/result/success, foreground turn completed
13:57:53  claude/system/task_notification, status: stopped
13:57:53  claude/system/task_updated, status: killed
13:57:54  runtime.error, message: "Claude runtime stream failed."
             failureTags: ["ProviderAdapterProcessError"]
13:57:54  session.exited, reason: "Session stopped", exitKind: "graceful"

# server.trace.ndjson for the second occurrence
claude.turn.result-without-active-turn
status: failed
hasUsage: false
errorMessage: "Claude runtime stream failed."

The bundled adapter maps any rejected Claude SDK stream to ProviderAdapterProcessError with the fixed detail Claude runtime stream failed.. The runtime event keeps only the failure count and tag, so the child process cause is lost.

Raw logs are not attached. They contain local paths, private commands, and authentication data.

Workaround

Starting a new Claude session recovers the thread. Avoiding run_in_background, or setting CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1, avoids this path but removes background work.

Suggested fix

Keep a failed or killed background task scoped to that task when no foreground turn is active. Stop or restart the idle Claude session without reporting a turn failure. Also retain the underlying SDK or child process cause in the redacted server log.

Related but different: #4198 covers the thirty-minute idle reaper. These two failures happened in less than eight minutes.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/server by tracing the bundled Claude adapter's rejected SDK stream handling and the runtime events for stopped or failed background tasks. Reproduce the sequence with a completed foreground turn and a background task that ends as failed or killed. Done means the task remains scoped to itself, the idle session does not report a turn failure, and the underlying cause is retained in redacted server logs.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.