pingdotgg / pingdotgg/t3code

[Bug]: Thread shows as live after the idle reaper has stopped its Claude Code process

Open
#9,586 0 comments 1 reaction 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

A thread idle 30 minutes still shows as live in T3 after the backend has stopped its Claude Code process. Peers lose it: ListAgents drops the thread, and SendMessage to its last address fails.

Before submitting
  • 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
  1. Open two Claude Code threads in the same working directory; send a turn in each.
  2. From thread A, call ListAgents; thread B is listed with a socket path.
  3. Leave thread B idle 30+ minutes, then SendMessage to that address from thread A.
Expected behavior

A thread shown as live stays addressable from its peers, or stops being shown as live. The ask: exempt sessions that are live cross-session messaging endpoints, in the same shape as the backgroundLiveness guard from #4198/#5677.

Actual behavior

Thread B is gone from the roster and the send fails; T3 shows no change.

It's the inactivity reaper — verified in ProviderSessionReaper.ts: DEFAULT_INACTIVITY_THRESHOLD_MS is 30 minutes, swept every 5, with exactly two exemptions, an active turn and backgroundLiveness (added by #5677 for #4198). Everything else past the threshold goes to providerService.stopSession. A thread idle because it's waiting to be messaged has neither exemption.

Resuming doesn't heal it: the roster is process-scoped (~/.claude/sessions/<pid>.json, socket /tmp/cc-socks/<pid>.sock), so the endpoint dies with the process. The conversation returns under a new pid, socket, and derived name (observed: "nameSource":"derived"), so addressing by roster name doesn't survive either.

Some of these peers are terminal sessions T3 never started, so the T3 process must stay on Claude Code's roster.

Impact

Major degradation or frequent failure

Version or commit

0.0.38 desktop (Alpha); citations against main @ 70cd258d

Environment

macOS 26.6.2 (Darwin 25.6.0), Node v26.3.1, Claude Code 2.1.259

Logs or stack traces
none — server.trace.ndjson rotates faster than the 30-min threshold
Workaround

Re-run ListAgents before every send and wake the target with a turn — which takes a human in that thread.

Related: #5523 asked to make the threshold configurable; this asks for an exemption, not a setting.

Drafted with Claude Code (Claude Opus 5) from source and transcripts on my machine; I reviewed and posted it.

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 and inspect ProviderSessionReaper.ts, especially DEFAULT_INACTIVITY_THRESHOLD_MS and the existing active-turn and backgroundLiveness exemptions. Trace how ListAgents and SendMessage depend on the Claude Code process, then add the requested exemption for live cross-session messaging endpoints and verify that idle addressable threads remain on the roster and reachable.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.