Repository navigation
bug: non-empty treePathExcludePatterns can leave initial project tree empty #5159
Description
Activity
Reproduced on
develop, and it is a tree-construction failure as you suspected — not a glob-rule configuration error. Fix in #5461.Reproduction
Temp project with
alpha.md,beta.md,nested/gamma.md, opened through the realEditorWindow.openFolderpath (watcher IPC +mt::open-directory) against a Playwright-attached build:treePathExcludePatternstree []alpha.md,beta.md,nested["*.no-such-ext"](matches nothing)empty ["beta.md"]empty Same on the
electron-builderpackaged app. So: any non-empty value, matching or not.The instrumentation you asked for
-
Persisted value and element types — correct: a plain
string[], exactly what the preferences text box writes viavalue.split(','). Never the problem. -
ignoredcallback calls and returns during initial traversal — it does not return. It throws, on the first path it is asked about:Error while watching files: TypeError: minimatchExports.minimatch is not a function at checkPathExcludePattern (out/main/index.js:1560:26) at ignored (out/main/index.js:5672:13) at matchPatterns ([email protected]/index.js:61:13) at FSWatcher._userIgnored ([email protected]/index.js:76:20) at FSWatcher._isIgnored ([email protected]/index.js:668:21) at NodeFsHandler._addToNodeFs ([email protected]/handler.js:583:26) -
add/addDirevents and renderer receipt order — none are emitted. chokidar raiseserrorinstead of traversing, so nothing ever reachesmt::update-object-tree. The renderer's pending-event queue and themt::open-directoryordering are both fine; there is simply nothing to queue.
Root cause
src/common/filesystem/paths.tsimports{ minimatch } from 'minimatch', but minimatch has never been a declared dependency — it has been a phantom dependency since #4001 introduced the import. Undershamefully-hoist=trueit resolved to whichever transitive copy won the rootnode_moduleshoist, which is minimatch@3. That version's CommonJS export is the function itself:module.exports = minimatch minimatch.Minimatch = Minimatch // no `minimatch.minimatch`
so the named import is
undefined.It stayed invisible because
src/types/shims.d.tshand-declared the module with an export that does not exist:declare module 'minimatch' { export function minimatch(target: string, pattern: string, options?: unknown): boolean }
typecheckandlinttherefore pass over a binding that can never exist at runtime.checkPathExcludePatternonly reaches the call inside its pattern loop, which is why the empty array works and every non-empty value fails — the loop body is the first and only thing that touchesminimatch.Your isolated test was right to clear chokidar and minimatch individually: each is fine on its own. The break is the module boundary between them, which only exists in the app's own bundle.
Fix
#5461 declares
minimatchas a real dependency and removes the shim so the package's own types apply. A side effect worth flagging:treePathExcludePatternsnow filters for the first time since #4001 — before this it either did nothing (empty) or blanked the tree (non-empty).-
Reported release behavior
In the released application, setting
treePathExcludePatternsto any non-empty value causes the sidebar project tree's initial scan to produce an empty tree. The same project can be scanned when the preference is an empty array.This should be treated as a sidebar watcher/tree-construction failure, not as an invalid-glob configuration report: a pattern that matches no path must not suppress the initial tree.
Expected behavior
treePathExcludePatternsshould hide only paths that match the supplied minimatch patterns. A non-matching non-empty pattern must leave the initial project tree equivalent to the empty-pattern case.What was checked
I inspected the official
v0.19.1macOS arm64 release artifact after verifying its SHA-256 against the published checksum.app.asarcontains the sameWatcherpredicate as thev0.19.1source tag.5.0.0and Electron42.1.0(Node24.15.0).addDirand Markdownaddevents.mt::update-object-tree/mt::open-directoryordering.Those checks confirm the intended source contract but do not explain the release symptom. In particular, there is not enough evidence to claim that Chokidar, minimatch, or the packaging pipeline is the root cause.
Requested investigation
Please investigate the live application path from preference persistence through watcher creation and renderer IPC delivery. Useful instrumentation would record:
treePathExcludePatternsvalue and its element types.ignoredcallback during initial traversal.add/addDirevents emitted by the watcher and the corresponding renderer receipt/order relative tomt::open-directory.Until that evidence exists, please do not classify this as a glob-rule configuration error or attribute it to a particular watcher/packaging dependency.
Reproduction data still needed
The report is based on observed release behavior. I could not reproduce an empty scan in an isolated execution of the release-bundled Chokidar using a non-matching pattern. A minimal project archive, the exact preference JSON, OS/version, and whether the folder is opened at startup versus interactively would make the failing integration path reproducible.