Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Bug] Idle sessions retain sync subscriptions and hundreds of TCP connections with few active tasks

Open
#1,822 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript

Research direction

Start with the document cache and activation in apps/cli/src/lib/loro/doc.ts, then read garbage-collection candidate enumeration and access preflight in apps/cli/src/lib/message-handler.ts. Review the controlled diagnostics for cache tracking and overlapping joins, then trace the renderer subscription paths in session-detail.tsx, session-chat-interface.tsx, roost-session-bridge.ts, and create-workspace-runtime.ts. Done means establishing reliable ownership and release for unused session documents and subscriptions while preserving active and background work.

Written by the indexing model from the issue text.

Description

Affected area

CLI / daemon

Installation method

Desktop release: Lody Nightly.

Lody version or commit

Lody Nightly 0.107.0-nightly.7.

Source inspected at 3231dd335. The relevant lifecycle logic also exists in the installed application bundle. This source revision is not a claim about the exact packaged commit.

Operating system

macOS 27.0.1, arm64. Stash 4.3.5 build 572, with TUN enabled.

What happened?

During normal use, the daemon retained about 405 SessionDocument objects and about 420 TCP connections with only 1–3 active sessions. A SessionDocument is an open session-state object that can retain a live sync subscription. Most connections went to the Streams service and continued receiving data or keepalives. These were not closed TCP connections left in an operating-system table.

At the same time, Stash TUN stopped admitting new connections promptly. Its internal accepted/closing connection count stayed at 512, with additional connections waiting for accept. Independent requests through TUN timed out. Requests through the explicit HTTP proxy reached the same target through the same proxy node.

Restarting only the Lody daemon reduced the load and restored TUN requests. The Stash processes, node selection, and network configuration remained unchanged:

Observation Before daemon restart After daemon restart
Cached SessionDocument objects About 405 Initially 0, then 127
Lody connections About 420 About 138 after subscriptions settled
Independent TUN probes 6 timeouts in 10 attempts 49 successful responses in 49 attempts

Later, the same daemon accumulated 261 cached documents and 278 connections. Restarting did not prevent renewed growth. This intervention supports the connection-load explanation, but it does not establish that every retained document was unnecessary or that this was the only trigger.

What did you expect?

Session documents and sync subscriptions that no longer have a consumer need a reliable release path. Viewing history, leaving a session, or returning a failed request must not leave subscriptions without an owner indefinitely.

Preserve active tasks, background work, and necessary sync. This report does not request immediate disconnection of every idle session or prescribe a connection limit or implementation.

How can we reproduce it?

The complete network incident is intermittent. There is no reliable minimal reproduction for the full accumulation yet. The field sequence was normal use with many historical sessions, few active tasks, rising retained connections, and repeated TUN failures.

Two reachable resource-release defects were reproduced separately with deterministic diagnostics:

  1. Cache and garbage-collection tracking can diverge. A session/goal access denial or an owner session/fork request against an archived source opens a SessionDocument before returning failure. The document remains cached without an entry in SessionTransientStore. After advancing a logical clock by one hour and running garbage collection, the diagnostic still reports one cached document and zero tracked sessions. Calling the real touchSession for that document, then advancing another hour, lets garbage collection release it. The diagnostic uses the real cache, transient store, garbage collector, and fork service. MessageHandler methods are compiled unchanged from their TypeScript AST into a minimal class. Document initialization, metadata, and transport use synthetic boundaries.
  2. Overlapping room joins can lose a release handle. Keep the initial room join pending, then call ensureDocRoomJoined(). Both joins return subscriptions, but both write to the same docSub. Destruction releases only the last handle. A diagnostic runs the installed bundle's original document and repository lifecycle methods with controlled attachment and in-memory replica I/O. The normal case ends with zero room references and zero transport attachments. The overlapping case retains one reference and one attachment after destruction.

These diagnostics establish reachable defects. They do not identify the creator of each document in the field incident or measure each defect's contribution.

How often does it happen?

Sometimes for the complete network incident. The two controlled lifecycle cases reproduce deterministically under their stated conditions.

Additional context

Relevant source locations at the inspected revision:

The renderer also extends subscription lifetime. Previously visited hidden child-session tabs can continue observing history every 15 seconds. After the last UI reference is released, the cached history reader can continue for 10 minutes. Those reads refresh the daemon's idle timestamp. Relevant code includes session-detail.tsx, session-chat-interface.tsx, roost-session-bridge.ts, and create-workspace-runtime.ts under packages/components/src.

Bulk archiving reduced the indexed unarchived session count from 79 to 6. Subsequent probes showed normal connectivity. A daemon restart also occurred during that interval, so the reduction cannot be attributed to archiving alone.

The field observations came from Nightly with cloud sync. The shared daemon lifecycle code is in this repository. The same remote-connection pressure was not reproduced in the local-only OSS build. No authenticated service failure, data corruption, or data loss was established.

The requested outcome is a clear ownership and release boundary for session documents and subscriptions. Stash exposes the impact in this environment. This report does not establish that all 405 documents leaked or require a particular transport optimization.

Before submitting
  • I searched the existing issues and did not find a duplicate.
  • This report concerns an open-source component in this repository, not a hosted service, Web or mobile app, account, or billing issue.
  • This is not a security vulnerability; security reports follow the repository's security policy.
  • I removed credentials, private source, conversations, prompts, personal data, and other sensitive information.
Dominant language
TypeScript
Stars
1.2k
Forks
141
Avg merge
12h 35m
Merged PRs (30d)
664

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

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.

More from LodyAI/Lody

All issues in LodyAI/Lody

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.