Skip to content

lstat on invalid path for static pattern + ignore pattern leads to EIO in some environments #499

Description

@brentobi

First of all: Thanks for the effort of maintaining this package!

lstat is called on invalid paths like /my/path/!*.bup.txt when an ignore pattern is given while globbing static patterns.

This is a non-issue in environments where this results in a ENOENT because fast-glob ignores those.
But it is probably incorrect / unintended and unnecessary.

In some environments this even leads to EIO errors,
e.g. in Podman machine/guest VM on Windows/Hyper-V host, where EIO probably comes from Windows complaining about a literal * in the filepath.
(contrary to Windows/WSL host for some reason; I plan to file a bug with Podman for the Hyper-V behaviour, too.)

Example

const fastGlob = require("fast-glob");

// files:
// +- fixture/foo.js
// +- fixture/foo.test.js

fastGlob.sync("foo.txt", { ignore: ["*.bup.txt"] }); // -> ['foo.txt']
fastGlob.sync("**.txt" , { ignore: ["*.bup.txt"] }); // -> ['foo.txt']

Actual behaviour

For both, static and dynamic patterns, the correct files are returned.

For the static pattern, we get ENOENT (on most envs) or EIO (i.e. on podman / Hyper-V):

Error: ENOENT: no such file or directory, lstat '/my/path/!*.bup.txt'
    at Object.lstatSync (node:fs:1716:25)
    at Object.read (/my/path/node_modules/@nodelib/fs.stat/out/providers/sync.js:6:30)
    at ReaderSync.statSync [as _statSync] (/my/path/node_modules/@nodelib/fs.stat/out/index.js:18:17)
    at ReaderSync._getStat (/my/path/node_modules/fast-glob/out/readers/sync.js:42:21)
    at ReaderSync._getEntry (/my/path/node_modules/fast-glob/out/readers/sync.js:31:32)
    at ReaderSync.static (/my/path/node_modules/fast-glob/out/readers/sync.js:21:32)
    at ProviderSync.api (/my/path/node_modules/fast-glob/out/providers/sync.js:22:29)
    at ProviderSync.read (/my/path/node_modules/fast-glob/out/providers/sync.js:14:30)
    at Array.map (<anonymous>)
    at getWorks (/my/path/node_modules/fast-glob/out/index.js:93:18) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'lstat',
  path: '/my/path/!*.bup.txt'
}

Expected behaviour
I would expect fast-glob not to lstat any incorrectly resolved paths at all to avoid errors of any kind in the first place.

Instead static / dynamic detection probably should take ignore / negative patterns into account, using @nodelib/fs.walk for dynamic negative patterns instead, even if the glob pattern itself is static.

Additional info
This happens because static / dynamic pattern detection only takes the glob patterns into account but then adds dynamic negative patterns to the static task (see tasks' generate method).

This eventually leads to dynamic ignore/negative patterns being statically resolved via require("node:path").resolve(...) in _getFullEntryPath.

P.S.: I am not using fast-glob directly (yet), but indirectly via "prettier" npm package through which I encountered this error. I decided to create this issue here because it is unexpected behaviour (at least to me) and a fix might benefit other users than prettier as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions