[BUG] Windows desktop (no WSL): idle sessions disconnect after ~15 min (session_keepalive_interval_ms = 0) and cross-session messages no longer wake them — regression since 2026-08-15

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 0 comments · opened Aug 15, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Related: #86563 — same zeroed keepalive flags, reported there for WSL bridged sessions. That author explicitly observed no symptom on Windows-native through 2026-08-14 ("same account, same flags, produced no symptom for months on Windows"). On my Windows-native setup (no WSL at all) the same ~15-minute idle death started on 2026-08-15. So this report (a) extends the problem to Windows-native with a date of onset, and (b) adds a message-delivery failure mode not covered there.

Environment

  • Claude Code 2.1.222 (Windows desktop app build; npm latest is 2.1.233 at time of writing — the desktop channel updates on its own cadence)
  • Windows 11 Home 10.0.26100, sessions run Windows-native, no WSL bridge involved
  • Multi-session setup: one orchestrator session + several worker sessions in the same workspace, coordinated via cross-session messages (send_message from the session-management tools)

What worked before (up to 2026-08-14)
The orchestrator distributed tasks to worker sessions by internal messages; idle workers picked them up automatically. Sessions stayed warm or woke up on incoming mail.

What happens since 2026-08-15

  1. An idle session disconnects after 900 s — [WarmLifecycle:session] Idle timeout reached, disconnecting local_… in main.log.
  2. A message sent to a sleeping session is queued but does NOT wake it — it sits unprocessed until the user manually types into that session. Orchestration silently stalls, and the sender gets no signal that the message wasn't processed.
  3. Worst case: a queued message can be RENDERED in the target session's transcript UI yet never reach the model's context at all (observed across a session reload/model switch — the session later has no knowledge of a message that is visibly present in its own transcript). The user sees the task "delivered" while the session never received it.

Config (same as #86563)
~/.claude.jsoncachedGrowthBookFeatures.tengu_bridge_poll_interval_config:

{
  "heartbeat_interval_ms": 0,
  "session_keepalive_interval_ms": 0,
  "session_keepalive_interval_v2_ms": 0
}

Manually setting non-zero values does not stick — the server-side flag refresh overwrites them back to 0 within hours (verified twice on 2026-08-15).

Log evidence (local time — four idle worker sessions dropping within one minute):

2026-08-15 12:40:41 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_0e491710-…
2026-08-15 12:40:50 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_4480f306-…
2026-08-15 12:40:52 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_365c9ccb-…
2026-08-15 12:40:55 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_afd701f8-…

Expected behavior
Either keep sessions warm (restore the keepalive default — the client schema itself defaults session_keepalive_interval_v2_ms to 120000 per #86563), or make an incoming cross-session message wake the target session — and persist queued messages reliably across reloads. The visible-but-undelivered message is the most confusing failure mode.

Current workaround
Every worker session runs a self-scheduled 5–10 min no-op wake loop (cron/ScheduleWakeup) to stay under the 900 s idle timeout, plus tasks are duplicated as files in a shared folder. Works, but burns quota on empty ticks and has to be re-armed every morning.

What Should Happen?

Idle sessions should stay reachable, as they were up to 2026-08-14: either keep them warm (restore the keepalive — the client schema itself defaults session_keepalive_interval_v2_ms to 120000 per #86563), or wake the target session when a cross-session message arrives. Queued messages must survive reloads instead of being rendered in the transcript UI without ever reaching the model — the sender should get some signal when delivery didn't happen. Expected behavior is yesterday's: orchestrator mail woke idle worker sessions automatically.

Error Messages/Logs

2026-08-15 15:07:16 [info] [WarmLifecycle:session] Starting idle timeout for local_76087652-…: 900s
2026-08-15 12:40:41 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_0e491710-…
2026-08-15 12:40:50 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_4480f306-…
2026-08-15 12:40:52 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_365c9ccb-…
2026-08-15 12:40:55 [info] [WarmLifecycle:session] Idle timeout reached, disconnecting local_afd701f8-…

Steps to Reproduce

  1. Windows desktop app (no WSL), one workspace, several sessions: one "orchestrator" + several workers.
  2. Leave a worker session idle for >15 minutes. main.log records [WarmLifecycle:session] Starting idle timeout for <sessionId>: 900s and then Idle timeout reached, disconnecting <sessionId>.
  3. From the orchestrator session, send that worker a message via the session-management send_message tool. The call succeeds ("Message queued...").
  4. Observe: the worker never processes it — no turn runs, no reply, for however long you wait. The message is only processed after the user manually types anything into that worker session.
  5. Delivery-loss variant: if the target session is reloaded (e.g. model switch) while the message is queued, the message can appear rendered in the target's transcript UI, yet the session's model context never receives it — the session later has no knowledge of a message visibly present in its own transcript.

Before 2026-08-15 step 4 behaved differently on this same setup: the queued message woke the idle worker and was processed automatically.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.222 — same build worked on 2026-08-14; the regression arrived via a server-side flag change, not an app update

Claude Code Version

2.1.222 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗