Repository navigation
Description
Summary
The background service caches loaded locations by directory path. When a directory is
deleted and recreated at the same path, the cached location is never invalidated: a newly
connected client receives the previously loaded location, so configuration and plugins are
those of the old incarnation. New/changed plugin files in the recreated directory are never
scanned; reopening the window does not help, and the watchers that were subscribed to the
old files are gone with the deleted directory.
Environment
- opencode version: 2.0.28
- OS: Linux 7.0.0-38-generic (Ubuntu 24.04, x86_64)
- Terminal: TERM_PROGRAM=herdr, TERM=xterm-256color, COLORTERM=truecolor
- Shell: /bin/sh
- Install/channel: latest (bun global install of
@opencode/cli) - Active plugins: several project-local plugins under
.opencode/plugin/, plus one
file://plugin from the global config
Reproduction
Setup: a checkout at $REPO with project-local plugins in $REPO/.opencode/plugin/*, plus
short-lived nested git worktrees at $REPO/sessions/<name> (linked worktrees of the same
repo, so each contains another copy of .opencode/plugin/* at the same relative paths).
The shared background service stays running the whole time.
- Open a client in
$REPO/sessions/agent0. Its plugin set is loaded; confirm with
GET /api/plugin?location[directory]=<dir>— e.g. the.sessioncopy of the plugins is
registered. - Close the client. Delete the worktree directory entirely (
git worktree remove+rm),
then re-create it at the same path (git worktree add … sessions/agent0). - Open a new client in
$REPO/sessions/agent0. GET /api/debug/locationstill lists the directory, and
GET /api/plugin?location[directory]=<dir>still returns the plugin set from the old
incarnation — the new copy of the plugins is never registered.
Expected Behavior
The server should detect that the directory was removed and recreated (identity/instance
change, or simply that it is missing and came back) and rebuild the loaded location, so the
client gets config/plugins that match the on-disk state. At minimum, provide a supported
(non-debug) way to evict/refresh a single location.
Actual Behavior
The new client keeps the stale location. Plugin-provided tools/guards silently do not
exist because the plugin files of the recreated directory are never loaded. Reopening the
window does not rescan. Verified workaround on 2.0.28 (rebuilds the plugin set correctly):
DELETE /api/debug/location?location[directory]=<dir>
GET /api/location?location[directory]=<dir>
Additional Context
- Related: cli: reload fails with 503 after a managed worktree directory is removed; stale location is never pruned #54827 (stale location is never pruned after an externally removed managed
worktree;opencode reloadfails once) and debug: evicting a loaded location recreates its project #51198 (debug evict semantics). - Frequency: deterministic in this workflow — any time a live worktree under the same path
is deleted and recreated while the shared background service keeps running. - Current mitigation on our side: tooling evicts the location via the debug API right after
such directories are removed/recreated (best-effort). A server-side fix (invalidate on
directory identity change, or prune locations whose directory is gone) would remove the
need for that.
Activity
opencode-agent commentedon Oct 13, 2026
Thanks for the detailed report. I reproduced this on 2.0.28, and it still happens on the latest
dev(23e3493).What I did, using the background service:
.opencode/plugin/alpha.tsand a linked worktree atsessions/agent0, then loaded that location./api/pluginlists both copies ofalpha.git worktree remove+rm, waited a few seconds, then rangit worktree addat the same path. I also added a newbeta.tsplugin and changedalpha.ts./api/debug/locationstill lists it, but/api/pluginonly shows the plugin from the main checkout. The recreated worktree's plugins are never loaded.DELETE /api/debug/location, thenGET /api/location) loads them correctly.The delay between deleting and recreating matters. When I recreated the worktree immediately, the server noticed the change and loaded the new plugins. With a gap of a few seconds it never does. The script below reproduces it.
Related: #54827 (stale location never pruned after a worktree is removed) and #51198 (debug evict behaviour).
Reproduction script (repro.sh)
Run it:
bash repro.shnakulmaurya commentedon Oct 13, 2026
I am investigating a focused fix on current dev (23e3493). I reproduced stale config/service reuse in the existing location-layer suite through get, contextEffect, and contextEffectOption. The candidate change compares local directory identity before reusing a cached graph and uses the existing invalidate/shutdown path when it changes. Workspace locations remain exempt from local probes, and optional lookups still do not create a graph.
I will add deletion/recreation and cache-preservation coverage and run the package checks before opening a PR. This is separate from #54878, which skips missing locations during explicit reload. Please let me know if this is already being worked on or a different invalidation approach is preferred. AI assistance is being used; I am running the checks locally.