You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Claude's wake turn after a background task is killed when the session is released before its first frame #37252
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
In a Claude thread, have the agent start a background Bash command (run_in_background) that takes a few seconds, and have it wait on that task through T3 (t3_background_wait).
Let the agent end its turn while the command is still running.
The command finishes. The Claude CLI emits task_notification and background_tasks_changed [], then starts its own wake turn for the notification.
If anything releases the provider session in the short window before the first frame of that wake turn arrives (idle release, a linked-environment change on open, or a detach), T3 sends query.close.
Expected behavior
The session stays open until Claude's wake turn starts. The agent wakes, reads the task output, and continues.
Actual behavior
T3 closes the Claude CLI 11 ms after the notification, while the CLI's wake request to the model is in flight. The wake turn never completes, nothing re-offers it, and the thread sits silent. In my case it stayed silent for 13 hours until I sent another message. The agent had promised to merge a PR as soon as the background task finished, and never did.
Cause, as far as I can tell: hasPendingBackgroundWork in ClaudeAdapterV2.ts returns false in that window. The internal roster is already empty, and the wake buffer holds only the task_notification. The probe counts only buffered user, assistant, or result frames, so a buffered notification for a wake that Claude is about to open doesn't count. Every release path that consults the probe then treats the process as idle.
I could not confirm which release path fired. The server traces had rotated past that time. The provider event log shows the close itself.
Impact
Major degradation or frequent failure
Version or commit
main @ 167f42e (2026-11-14). The same code is on main @ 256dce7.
Environment
macOS, T3 Code server, Claude Code 2.1.325 via the Agent SDK, claude-opus-5-5
Logs or stack traces
02:12:24.649Z incoming result success end_turn # root turn ends; background Bash task still running
02:12:27.305Z incoming system task_notification completed # background task done
02:12:27.305Z incoming system background_tasks_changed []
02:12:27.316Z outgoing query.close # T3 closes the CLI 11 ms later
02:12:27.370Z (CLI transcript) api-request for the wake turn # never answered
15:08:34.801Z outgoing query.open # next user message, 13 hours later
Workaround
Send any message to the thread. The agent then has to rediscover what the background task produced.
More data. I scanned my local provider event logs for a background task_notification followed by query.close, with no assistant or result frame in between. It happened 11 times in 3 days (Nov 12 to 15), across 9 Claude threads. The gap from notification to close was 8, 11, 11, 14, 14, 18, 20, 24, 37, 68, and 130 ms.
The close always lands within milliseconds of the notification. So the notification and the roster emptying seem to trigger the release, rather than an unrelated timer happening to fire in the window. In each case the agent had said it would act when the background task finished, and then went silent.
A second instance from a different thread, in the same shape:
22:56:30.030Z incoming result success end_turn
23:02:20.878Z incoming system task_notification completed
23:02:20.879Z incoming system background_tasks_changed []
23:02:20.886Z outgoing query.close
I tried to reproduce this on the current build and could not.
Commit origin/main 14f295e. Isolated server (node apps/server/src/bin.ts serve --base-dir <scratch home> with T3CODE_DEV_SEED=0, fresh database), real Claude Code 2.1.325, model claude-haiku-5-5, driven with t3 thread start/send/show. Prompt: run sleep 15; echo <token> with Bash run_in_background, end the turn at once, reply with the output when it finishes. (1) Control with no release: task_notification at 15:35:48.475, wake init at 48.560, first wake assistant frame at 51.864, result at 53.593; the wake reply arrived. (2) Linked-environments recycle on open: set linkedEnvironmentsEnabled=true in settings.json after the root turn, then thread send as soon as task_notification reached the provider log. The send returned Queued. because the thread was already busy from the wake's init frame. The only query.close (15:41:46.247) came after the wake's result, and the wake reply BG_DONE_32113 was shown. (3) Idle release with DEFAULT_IDLE_TIMEOUT_MS shortened locally to 1000 ms (not committed, reverted): 13 idle-release-deferred rechecks at 1 s intervals while the task ran (last at 15:43:51.591). task_notification at 51.699 cancelled the pending recheck, the wake completed (BG_DONE_18655) and query.close came at 58.791, after its result. So on these two paths the wake survived; the reporter's 11 ms close points at a trigger I could not identify. The probe defect itself is shown by a unit test: in ClaudeAdapterV2.test.ts 'buffers wake output and requests a single continuation run', after the wake task_notification is buffered (wake not yet started), hasPendingBackgroundWork returns false. Flipping that assertion to isTrue fails on main (+ false).
Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.
Activity
mvanhorn commentedon Nov 15, 2026
More data. I scanned my local provider event logs for a background
task_notificationfollowed byquery.close, with no assistant or result frame in between. It happened 11 times in 3 days (Nov 12 to 15), across 9 Claude threads. The gap from notification to close was 8, 11, 11, 14, 14, 18, 20, 24, 37, 68, and 130 ms.The close always lands within milliseconds of the notification. So the notification and the roster emptying seem to trigger the release, rather than an unrelated timer happening to fire in the window. In each case the agent had said it would act when the background task finished, and then went silent.
A second instance from a different thread, in the same shape:
#37253 has the fix.
juliusmarminge commentedon Nov 15, 2026
I tried to reproduce this on the current build and could not.
Commit origin/main 14f295e. Isolated server (
node apps/server/src/bin.ts serve --base-dir <scratch home>with T3CODE_DEV_SEED=0, fresh database), real Claude Code 2.1.325, model claude-haiku-5-5, driven witht3 thread start/send/show. Prompt: runsleep 15; echo <token>with Bash run_in_background, end the turn at once, reply with the output when it finishes. (1) Control with no release: task_notification at 15:35:48.475, wake init at 48.560, first wake assistant frame at 51.864, result at 53.593; the wake reply arrived. (2) Linked-environments recycle on open: set linkedEnvironmentsEnabled=true in settings.json after the root turn, thenthread sendas soon as task_notification reached the provider log. The send returnedQueued.because the thread was already busy from the wake's init frame. The only query.close (15:41:46.247) came after the wake's result, and the wake reply BG_DONE_32113 was shown. (3) Idle release with DEFAULT_IDLE_TIMEOUT_MS shortened locally to 1000 ms (not committed, reverted): 13 idle-release-deferred rechecks at 1 s intervals while the task ran (last at 15:43:51.591). task_notification at 51.699 cancelled the pending recheck, the wake completed (BG_DONE_18655) and query.close came at 58.791, after its result. So on these two paths the wake survived; the reporter's 11 ms close points at a trigger I could not identify. The probe defect itself is shown by a unit test: in ClaudeAdapterV2.test.ts 'buffers wake output and requests a single continuation run', after the wake task_notification is buffered (wake not yet started),hasPendingBackgroundWorkreturns false. Flipping that assertion to isTrue fails on main (+ false).Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.