You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bug: file watcher paths stop matching open files on Windows #17780
On Windows, file watcher updates can fail to refresh both:
files shown in the file tree
files already open in tabs
This happens when watcher events use backslash-separated paths while the app store / tab state uses slash-separated paths.
As a result, external file changes or tool-driven edits can be missed even though the watcher event itself arrives.
In my testing, this is not limited to unloaded descendants. Directory contents can also fail to refresh even when the relevant directory is already visible.
Steps to reproduce
Run OpenCode on Windows.
Open a file in a tab.
Modify that file through a tool action or an external process.
Observe that the open tab content does not always refresh.
Create, remove, or change files in a directory shown in the file tree.
Observe that directory contents may fail to refresh in the file tree, including cases where the directory is already visible.
Expected behavior
Watcher paths should match store/tab paths consistently on Windows.
Open files should refresh when watcher updates arrive.
File tree refresh should work reliably when directory contents change.
Actual behavior
Watcher updates can be ignored because normalized paths do not match.
Open tabs stay stale.
File tree refresh can be skipped or missed when directory contents change.
Suspected cause
normalize() can preserve Windows \ separators for watcher-originated paths, while other app paths are compared in / form.
There also appears to be a watcher refresh gap in directory invalidation / refresh behavior, not just a path-key mismatch.
Proposed fix
Normalize watcher path comparisons consistently so Windows paths match the existing store/tab keys.
Make watcher-driven directory refresh behavior reliable when file system changes occur, including directories that are already visible.
Additional context
This may be related to the separator-preserving behavior introduced for Windows / Cygwin compatibility in PR #14912: #14912
However, the current behavior appears to break watcher-to-store comparisons in the app UI and also misses some file tree refresh cases.
These issues share the same root cause (Windows \ vs / path normalization), though #17780 specifically targets the file watcher → store/tab comparison path. If the fix scope overlaps, it may make sense to consolidate.
They do seem to share the same broader Windows path canonicalization root cause (\ vs /, and possibly drive-letter normalization), especially for the path comparison part.
That said, this issue is focused on a narrower but still distinct failure path in the app UI:
watcher event path -> store/tab path comparison for already-open files
watcher-driven file tree refresh behavior
In my testing, this is not limited to unloaded descendants. Directory contents can also fail to refresh even when the relevant directory is already visible.
So I think this issue is related to #12940, #14570, and #17183, but not fully covered by them unless the eventual fix is intentionally broadened to include the watcher/store-tab comparison path and the watcher-driven directory refresh path as well.
Leaving a detailed status note here in case it helps the next person who looks at this.
I checked origin/dev again before writing this comment. As of today, this issue still appears unresolved in the tree:
packages/app/src/context/file/path.ts still preserves native Windows separators in normalize()
packages/app/src/context/file/watcher.ts still bails out on add / unlink when the immediate parent is not loaded instead of walking up to the nearest loaded ancestor
the issue is still open
I attempted an upstream fix in PR #17794 and ended up closing it after multiple rounds because I could not get it to a trustworthy state within a reasonable cost budget.
What I changed in that attempt
Watcher / open-file path normalization on Windows
normalized watcher-side paths so \ and / stop diverging between watcher events and store/tab keys
adjusted directory invalidation so file tree refresh could walk upward to the nearest loaded ancestor instead of only refreshing the immediate parent
Follow-up fix for Windows e2e failure
the PR initially triggered a Windows e2e failure in e2e/prompt/prompt-mention.spec.ts
I reproduced that locally and traced it to two things:
file search could return an empty result before the initial file index finished
Windows file search / fuzzy matching was still inconsistent between \ and /
I added a fix so the first search waits for initial indexing and the search side compares normalized separators consistently
after that, the Windows @mention failure passed in CI
Follow-up fix for Linux e2e failure
after the Windows failure was fixed, CI still failed on Linux in e2e/session/session-composer-dock.spec.ts, specifically blocked question flow unblocks after submit
that one was not failing in app logic; it was timing out while seeding a pending question request for the test
I traced that to the test using a live model-driven seed path for question requests, while the sibling permission tests already used deterministic route mocks
I rewrote the question-dock tests to use mocked /question list/reply/reject endpoints so the test only exercised the dock behavior instead of depending on an LLM/tool round-trip
that spec passed locally after the change
Why I closed the PR anyway
even after the Windows mention fix and the Linux question-dock stabilization attempt, I still could not get the overall PR into a state where I was confident enough to keep asking CI to validate guesses
my local Windows environment also had unrelated noise that made iteration expensive:
the known symlink problem around packages/app/src/custom-elements.d.ts and packages/enterprise/src/custom-elements.d.ts
local full e2e instability unrelated to the original watcher bug
at that point I had already spent far too much token / debugging budget on the submission and stopped rather than continuing to churn CI with low confidence
What I was able to confirm with high confidence
the original watcher/open-tab problem is real
normalize() preserving native separators on Windows is definitely part of the problem
watcher refresh behavior also has a separate gap for directory invalidation / refresh
fixing the watcher bug exposed or intersected with at least one additional Windows path/search issue in prompt-mention.spec.ts
there was also a flaky Linux e2e in the same PR attempt, but that one looked like test seeding instability rather than the watcher bug itself
What I was not able to deliver confidently
a final upstream PR that fixed the watcher issue and also left the full CI suite in a clearly green, low-risk state
a clean separation between "watcher fix side effects" and "pre-existing flaky CI" that I would be comfortable asking maintainers to trust without further iteration
If someone takes another run at this, my recommendation would be:
keep the watcher/path fix itself as small as possible
treat Windows watcher normalization and directory refresh as the primary bug
expect prompt-mention.spec.ts to be a likely regression surface on Windows
if Linux session-composer-dock.spec.ts fails again, treat that as a separate flaky-test cleanup rather than evidence that the watcher fix is conceptually wrong
Activity
github-actions commentedon Mar 16, 2026
This issue might be a duplicate of (or closely related to) existing issues around Windows path separator normalization. Please check:
These issues share the same root cause (Windows
\vs/path normalization), though #17780 specifically targets the file watcher → store/tab comparison path. If the fix scope overlaps, it may make sense to consolidate.jb-sk commentedon Mar 16, 2026
Thanks, I checked those issues.
They do seem to share the same broader Windows path canonicalization root cause (
\vs/, and possibly drive-letter normalization), especially for the path comparison part.That said, this issue is focused on a narrower but still distinct failure path in the app UI:
In my testing, this is not limited to unloaded descendants. Directory contents can also fail to refresh even when the relevant directory is already visible.
So I think this issue is related to #12940, #14570, and #17183, but not fully covered by them unless the eventual fix is intentionally broadened to include the watcher/store-tab comparison path and the watcher-driven directory refresh path as well.
jb-sk commentedon Mar 18, 2026
Leaving a detailed status note here in case it helps the next person who looks at this.
I checked
origin/devagain before writing this comment. As of today, this issue still appears unresolved in the tree:packages/app/src/context/file/path.tsstill preserves native Windows separators innormalize()packages/app/src/context/file/watcher.tsstill bails out onadd/unlinkwhen the immediate parent is not loaded instead of walking up to the nearest loaded ancestorI attempted an upstream fix in PR #17794 and ended up closing it after multiple rounds because I could not get it to a trustworthy state within a reasonable cost budget.
What I changed in that attempt
Watcher / open-file path normalization on Windows
\and/stop diverging between watcher events and store/tab keysFollow-up fix for Windows e2e failure
e2e/prompt/prompt-mention.spec.ts\and/@mentionfailure passed in CIFollow-up fix for Linux e2e failure
e2e/session/session-composer-dock.spec.ts, specificallyblocked question flow unblocks after submit/questionlist/reply/reject endpoints so the test only exercised the dock behavior instead of depending on an LLM/tool round-tripWhy I closed the PR anyway
packages/app/src/custom-elements.d.tsandpackages/enterprise/src/custom-elements.d.tsWhat I was able to confirm with high confidence
normalize()preserving native separators on Windows is definitely part of the problemprompt-mention.spec.tsWhat I was not able to deliver confidently
If someone takes another run at this, my recommendation would be:
prompt-mention.spec.tsto be a likely regression surface on Windowssession-composer-dock.spec.tsfails again, treat that as a separate flaky-test cleanup rather than evidence that the watcher fix is conceptually wrongHope this saves somebody else some time.
github-actions commentedon Jul 7, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.