Glob order matters for negated wildcard paths when it shouldn't
- Dominant language
- JavaScript
- Stars
- 32.9k
- Forks
- 4.1k
- PR merge metrics
- No merged PRs in 30d
Description
Before you open this issue, please complete the following tasks:
* [x] use the search bar at the top of the page to search this repository for similar issues or discussions that have already been opened.
* [x] if you are looking for help from the gulp team or community, open a [discussion](https://github.com/gulpjs/gulp/discussions).
* [x] if you think there is a problem with the plugin you're using, open a [discussion](https://github.com/gulpjs/gulp/discussions).
* [x] if you think there is a bug in our code, open this issue.
### What were you expecting to happen?
The [docs for globs](https://gulpjs.com/docs/en/getting-started/explaining-globs) in `gulp.src` seem to indicate that order should not matter. Up until now this has always seemed to be the case.
We are using `gulp.src` to select a number of files across our project including a mix of wildcard `**` and single file globs. I wanted to negate a nested directory using another `**` wildcard path and put it next to the "parent" directory in the list for organization. However this seems to fail unless the negated path is at the end of the array.
```
Error: File not found with singular glob: /[path]/test-gulp/test.config (if this was purposeful, use `allowEmpty` option)
```
If the order _does_ matter I think it would be good to point that out more in the docs and provide a more clear error message that this may be the case. Right now that error message implies that a file that _does_ exist does not.
### Please give us a sample of your gulpfile
Given a fresh project with the following structure:
```
.
├── gulpfile.js
├── issue
├── package.json
├── src
│ ├── exclude
│ │ └── file2.txt
│ └── file1.txt
└── test.config
```
Setup commands
```sh
mkdir test-gulp
cd test-gulp
mkdir -p src/exclude
touch src/file1.txt
touch src/exclude/file2.txt
touch test.config
npm init -y
npm install gulp
```
```js
import gulp from 'gulp';
import { Transform } from 'readable-stream';
gulp.task(function testSource(cb) {
const files = gulp.src(
[
'src/**',
// '!src/exclude/**', // <-- if put here it will fail without allowEmpty
'test.config',
'!src/exclude/**', // <-- if put here it will work regardless
],
{
// allowEmpty: true,
}
);
files.pipe(
new Transform({
objectMode: true,
transform: (file, _, cb) => {
// simple stream to log the files it's working on
console.log(file.path);
cb(null, file);
},
})
);
cb();
});
```
### Terminal output / screenshots
```sh
npx gulp testSource
```
should output
```
/[path]/test-gulp/src/file1.txt
/[path]/test-gulp/test.config
```
but if you put the negated path for `src/exclude` _before_ the `test.config` path it errors with
```
Error: File not found with singular glob: /[path]/test-gulp/test.config (if this was purposeful, use `allowEmpty` option)
```
If you add `allowEmpty: true` to the options it does work again and output the 2 files shown above. However I would ideally like to keep `allowEmpty` off to catch actual issues with the build and missing files.
### Please provide the following information:
* OS & version [e.g. MacOS Catalina 10.15.4]: Kubuntu 25.04
* node version (run `node -v`): 20.19.2
* npm version (run `npm -v`): 11.4.2
* gulp version (run `gulp -v`): 5.0.1
Contributor guide
Assessment
This issue has not been assessed yet.