Repository navigation
fix(core): skip location watcher outside VCS projects #35813
Description
Summary
OpenCode V2 starts a recursive Parcel watcher for every non-home Location, even when the Location is not a VCS project. On a large non-Git working directory this can leave tens of thousands of inotify watches alive after the 10-second subscription timeout, consume substantial kernel memory, and push a long-running host toward its memory ceiling.
This is the V2/Core continuation of the broader symptom reported in #23190. The concrete missing invariant here is that LocationWatcher should not register at all when location.vcs is absent.
Environment
- opencode version: V2 pinned at
8deb0e5780dc83160a9ec12e6476e36267f82948 - OS: Linux 6.12.93 x86_64
- Terminal: Not applicable; observed in a headless OpenCode Agent service
- Shell: Not applicable
- Install/channel: Immutable OpenCode Agent production release; OpenCode built from source
- Active plugins: Unavailable; no plugin is involved in watcher registration
Reproduction
- Start OpenCode V2 with a non-home, non-VCS Location containing a very large directory tree. The observed Location contained about 479,000 directories, including 131 task worktrees with about 468,000 directories under the worktree tree, but the Location root itself had no
.gitentry. - Allow Location services to boot.
LocationWatcher.nodeis included unconditionally inlocationServices. - Observe
LocationWatchercallwatcher.subscribe({ path: location.directory, type: "directory", ... })because the Location is not exactly$HOME; this branch does not checklocation.vcs. - Wait for the 10-second subscription timeout and inspect
/proc/<pid>/fdinfo/*.
Expected Behavior
A Location without VCS metadata should not register the recursive location watcher. The Git metadata watcher is already conditional on location.vcs?.type === "git"; the broad Location watcher should preserve the same VCS-project boundary.
Actual Behavior
The broad Location subscription is unconditional for every Location except exact $HOME.
In the production incident:
- Startup logged
failed to subscribefor the non-Git Location after 10 seconds. - The live service still had two inotify instances: 458 watches for config directories and 82,502 watches attributable to the pending broad Location subscription.
- During the incident investigation, the retained watch set was estimated to account for roughly 1 GiB of kernel slab at peak and contributed to the host approaching its memory ceiling.
- The timeout handler calls
pending.then(subscription => subscription.unsubscribe()), so cleanup cannot happen until Parcel's native recursive subscription finishes and resolves. The timeout does not cancel traversal or remove watches already installed while it remains pending.
Additional Context
The exact registration paths are:
- Config watcher: global config and discovered
.opencodedirectories. - Location watcher: the entire Location recursively, with static ignore patterns.
- Git metadata watcher: separately guarded by
location.vcs?.type === "git".
Current consumers of filesystem.changed are skill-cache invalidation and web/desktop file-tree or VCS refresh. In the headless Agent runtime only skill invalidation consumes these events. Normal .opencode/skills changes are also covered by the config watcher through config.updated; broader configured skill paths can still use Location events inside actual VCS projects.
The smallest fix is an early return in LocationWatcher when location.vcs is absent, plus changing the existing test that currently asserts non-Git roots are watched.
Related issue: #23190 documented hangs in large non-Git directories and was closed automatically for inactivity.
Production evidence window: 2026-07-07 22:45 UTC through 2026-07-08 00:20 UTC.
Source discussion: https://discord.com/channels/1391832426048651334/1521893148220199002/1524176536159125636
OpenCode Agent diagnostic identities (for internal correlation):
- OpenCode Session:
ses_agent_6ecee8df-cd50-491b-ab66-83fac776da16 - AgentSession:
6ecee8df-cd50-491b-ab66-83fac776da16 - Triggering input:
slack:1783468015.936579 - Active OpenCode Agent release:
5e15fd408ea7609ab51eb9117dc84dc000d942c0_8deb0e5780dc83160a9ec12e6476e36267f82948
Activity
opencode-agent commentedon Jul 8, 2026
Active implementation: draft V2 PR #35818.
opencode-agent commentedon Jul 9, 2026
Closing as fixed on current origin/v2.
LocationWatchernow only starts the recursive location watcher whenlocation.vcsis present (commit 86e3828,fix(core): watch location only when vcs is present). PR #35818 appears obsolete/stale.