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] Location inactivity eviction SIGTERMs live background shells after 60 minutes #51828
Background shells are SIGTERM'd when LocationActivity evicts their
location after 60 minutes without session events. Service stays alive
(same PID); only the location-scoped Shell/Pty graph is torn down by locations.invalidate().
Timeline 2026-09-27 (service 2.0.10): location services evicted directory=/data3/zsy/asr2report_pipeline 16:24:48.527Z → torchrun Received 15 death signal 16:24:48.563Z → payload handler rc=143, signal=15. No service restart near the window.
Steps to reproduce
serve, create a background shell with a long command
(POST /api/shell, e.g. sleep 4000), then leave the location idle
(no session events).
Wait past the 60-minute TTL: the sweep expires the entry and calls locations.invalidate(), killing the child.
Root cause
The sweep only exempts locations owning active SessionExecution
sessions (location-activity.ts). A backgrounded shell/pty emits no
session events and holds no execution claim, so it looks idle.
This issue might be a duplicate of existing issues. Please check:
#48691: Reports terminals killed when a location is evicted after 60 minutes; the same inactivity eviction tears down live shell/PTY processes.
#51343: Reports 60-minute location eviction interrupting a still-running session and background work; the underlying location-activity eviction behavior is closely related.
Second independent instance of background-shell completion loss (v2.0.22)
Independent confirmation of the exact symptom, with the completion notification proven absent from storage.
Session ses_efeb61f29ffeWnthm3xB8kevap, background shell job sh_10280cd3f001TXnljvbScsSUtv (launched 18:02:34). Session ended its turn at 18:03:05 (last durable event in the location). Location idle TTL elapsed ~19:03; the job actually finished 19:11:33. No notification was ever delivered; session was woken manually at 20:11.
No synthetic row with that shellID anywhere in session_message — if delivery had happened the append-only row would exist.
session_inbox / session_pending empty for the session — rules out "admitted but wake dropped".
No server restart in the window (NRestarts=0), so restart recovery did not run.
.out file removed, matching the watcher's interrupt finalizer (tool/plugin/shell.ts:234).
Control: a second background: true job in the same session ran ~17 min and delivered a synthetic ({source:"shell", shellID, jobID, state:"completed", exit:0}) normally.
Root mechanism: ShellTool.notifyWhenDone is Effect.forkIn(scope, …) into the location/plugin scope (tool/plugin/shell.ts:154-186); the LocationActivity sweep interrupts owners and calls locations.invalidate(ref) (location-activity.ts:51,77-81), closing that scope and interrupting the watcher before sessions.synthetic(...) runs. The job process itself survives (detached), so the command completes with nowhere to report.
Detail for matching duplicates: the deadline is idle time since the last durable event in the location (1-min sweep), not job runtime — any background: true job expected to outlive ~60 min of location inactivity loses its completion notification.
The installed client has two local UI-only patches (composer visibility and location-less forms); the affected Core lifecycle code was unchanged when observed.
Production has two local plugins for continuity metadata and session-history archival. The accelerated reproduction used an isolated profile without those plugins, synthetic data and no external model calls.
Observed behavior
A read-only observation command was launched through the agent's shell tool with background: true and timeout: 0, intended to run for 75 minutes. It wrote its own timestamps and an interruption receipt.
The observation ran for 3,700.6 seconds and retained 62 samples. Its on-disk summary survived, but the owning session did not automatically receive a completion summary. The eviction and 404 share the same server run ID; this event was Location eviction, not a server restart.
Reproduction
Ask the agent to start a harmless long-running shell, e.g. sleep 4500; printf 'BACKGROUND_DONE\n', with background: true and timeout: 0.
Let the agent become idle and avoid further durable Session activity in that Location.
Wait beyond the 60-minute Location idle TTL and sweep interval.
Observe Location eviction, loss of shell observability, and the missing automatic completion notification.
The threshold is time since the Location's last relevant activity, not a fixed timeout measured from process startup.
Source analysis and local verification
In the tested baseline, packages/core/src/location-activity.ts only refreshed activity from durable Session events. The background Shell and ShellTool.notifyWhenDone observer have Location-owned lifetimes. Eviction can tear down both while the owning session is idle.
An isolated local candidate checks the already-cached Shell service for running commands before idle eviction, refreshes activity on shell creation/exit, and rechecks the activity entry before invalidation. This is supporting evidence, not a claim that either upstream PR has been tested or merged.
Validation:
Accelerated real-child reproduction: 1-second Location TTL, 3-second command. Unpatched success/nonzero cases lost the Location before completion.
Patched success, nonzero exit, timeout and explicit cancellation each admitted a notification and woke the original session once; notification markers were acknowledged and ordinary idle eviction resumed afterward.
67 lifecycle/restart/Job/Shell tests passed; Core typecheck and root bun run check passed.
Compiled candidate, isolated service and loopback model fixture: background command -> synthetic completion notice -> model wake -> automatic assistant summary passed for exit 0 and exit 7.
Six additional macOS bash-related tool-shell tests failed identically on the unchanged baseline; these are not claimed as passing.
The candidate has not been activated in production, and a full-length production soak of it is still pending. Actual server-restart recovery (resume: false for idle shell owners) is a separate behavior, not addressed by this idle-eviction change.
Related pending fixes: #52580 and #51827. Please include completion-notification delivery/owner wake, not only child-process survival, in regression coverage.
Cross-link: #55305 asks for the 60-minute location TTL to be configurable (or opt-out).
Same root cause as this report — LocationActivity's deadline expires an idle location, and the eviction tears down the location-scoped Shell/Pty graph. If the exemption logic discussed here lands, the knob may still be wanted for hosts that intentionally stay idle for long periods (an agent waiting on a human answer), which is what #55305 covers. Other surfaces of the same deadline: #51343 (running session interrupted), #48691 (terminals killed).
Activity
github-actions commentedon Sep 28, 2026
This issue might be a duplicate of existing issues. Please check:
SamSpiri commentedon Oct 3, 2026
Second independent instance of background-shell completion loss (v2.0.22)
Independent confirmation of the exact symptom, with the completion notification proven absent from storage.
Session
ses_efeb61f29ffeWnthm3xB8kevap, background shell jobsh_10280cd3f001TXnljvbScsSUtv(launched 18:02:34). Session ended its turn at 18:03:05 (last durable event in the location). Location idle TTL elapsed ~19:03; the job actually finished 19:11:33. No notification was ever delivered; session was woken manually at 20:11.syntheticrow with thatshellIDanywhere insession_message— if delivery had happened the append-only row would exist.session_inbox/session_pendingempty for the session — rules out "admitted but wake dropped".NRestarts=0), so restart recovery did not run..outfile removed, matching the watcher's interrupt finalizer (tool/plugin/shell.ts:234).background: truejob in the same session ran ~17 min and delivered asynthetic({source:"shell", shellID, jobID, state:"completed", exit:0}) normally.Root mechanism:
ShellTool.notifyWhenDoneisEffect.forkIn(scope, …)into the location/plugin scope (tool/plugin/shell.ts:154-186); theLocationActivitysweep interrupts owners and callslocations.invalidate(ref)(location-activity.ts:51,77-81), closing that scope and interrupting the watcher beforesessions.synthetic(...)runs. The job process itself survives (detached), so the command completes with nowhere to report.Detail for matching duplicates: the deadline is idle time since the last durable event in the location (1-min sweep), not job runtime — any
background: truejob expected to outlive ~60 min of location inactivity loses its completion notification.(Also posted a longer version on #52908.)
TonyYanS commentedon Oct 9, 2026
Independent confirmation on 2.0.24: live shell terminated and automatic summary lost
Environment
e7a34f09bfd9134dfade5a8ddb843f7030bc9a69./bin/zsh.Observed behavior
A read-only observation command was launched through the agent's
shelltool withbackground: trueandtimeout: 0, intended to run for 75 minutes. It wrote its own timestamps and an interruption receipt.Redacted timeline (UTC, 2026-10-09):
The observation ran for 3,700.6 seconds and retained 62 samples. Its on-disk summary survived, but the owning session did not automatically receive a completion summary. The eviction and 404 share the same server run ID; this event was Location eviction, not a server restart.
Reproduction
sleep 4500; printf 'BACKGROUND_DONE\n', withbackground: trueandtimeout: 0.The threshold is time since the Location's last relevant activity, not a fixed timeout measured from process startup.
Source analysis and local verification
In the tested baseline,
packages/core/src/location-activity.tsonly refreshed activity from durable Session events. The background Shell andShellTool.notifyWhenDoneobserver have Location-owned lifetimes. Eviction can tear down both while the owning session is idle.An isolated local candidate checks the already-cached Shell service for running commands before idle eviction, refreshes activity on shell creation/exit, and rechecks the activity entry before invalidation. This is supporting evidence, not a claim that either upstream PR has been tested or merged.
Validation:
bun run checkpassed.The candidate has not been activated in production, and a full-length production soak of it is still pending. Actual server-restart recovery (
resume: falsefor idle shell owners) is a separate behavior, not addressed by this idle-eviction change.Related pending fixes: #52580 and #51827. Please include completion-notification delivery/owner wake, not only child-process survival, in regression coverage.
AlexeyShirshov commentedon Oct 14, 2026
Cross-link: #55305 asks for the 60-minute location TTL to be configurable (or opt-out).
Same root cause as this report —
LocationActivity's deadline expires an idle location, and the eviction tears down the location-scoped Shell/Pty graph. If the exemption logic discussed here lands, the knob may still be wanted for hosts that intentionally stay idle for long periods (an agent waiting on a human answer), which is what #55305 covers. Other surfaces of the same deadline: #51343 (running session interrupted), #48691 (terminals killed).