gulpjs / glob-stream

Readable streamx interface over anymatch.
MIT License
178 stars 51 forks source link

Sourcing files from a folder that doesn't exist using a glob pattern gives a cryptic error instead of nothing happening #134

Open datho7561 opened 7 months ago

datho7561 commented 7 months ago

What were you expecting to happen?

Nothing (build succeeds with v4)

What actually happened?

Cryptic error

Please give us a sample of your gulpfile

Minimal reproducer: https://github.com/datho7561/gulp-glob-src-bug-reproducer

Terminal output / screenshots

npm run build

> example-gulp@0.1.0 build
> gulp my-broken-task

[17:27:38] Using gulpfile ~/Documents/Projects/example-gulp/gulpfile.js
[17:27:38] Starting 'my-broken-task'...
[17:27:38] Finished 'my-broken-task' after 4.52 ms
node:events:492
      throw er; // Unhandled 'error' event
      ^

<ref *2> Error: ENOENT: no such file or directory, scandir '/home/davthomp/Documents/Projects/example-gulp/libs'
Emitted 'error' event on Domain instance at:
    at Transform.emit (node:domain:539:12)
    at ReadableState.afterDestroy (/home/davthomp/Documents/Projects/example-gulp/node_modules/streamx/index.js:493:19)
    at Transform._destroy (/home/davthomp/Documents/Projects/example-gulp/node_modules/streamx/index.js:629:5)
    at ReadableState.updateNonPrimary (/home/davthomp/Documents/Projects/example-gulp/node_modules/streamx/index.js:386:16)
    at ReadableState.update (/home/davthomp/Documents/Projects/example-gulp/node_modules/streamx/index.js:367:71)
    at ReadableState.updateReadNT (/home/davthomp/Documents/Projects/example-gulp/node_modules/streamx/index.js:536:10)
    at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {

Followed by a large JavaScript object output as JSON

Please provide the following information:

Additional information

I think it's good that sourcing files from a folder that doesn't exist causes the build to fail, but I think the error message should be more clear and less noisy.

phated commented 7 months ago

Thanks for the report. I think I know where to fix this but it'll take some time.

We'll probably move this issue over to the glob-stream repository, as that's where the bug exists.

scottlet commented 7 months ago

I also hit this trying to upgrade to Gulp 5. Gulp 4 used to silently skip missing directories, is there any plan to support an option to include this behaviour in 5? I’d like to not have to test every directory exists before trying to copy it as I’m not responsible for the sources that may or may not exist

tinogo commented 6 months ago

I've just stumpled upon this error, too. Would be really nice, if you could introduce an option to "restore" the old behaviour. :)

phated commented 6 months ago

@tinogo it's a bug. We'll fix it when we have time.

pavelhoral commented 5 months ago

FYI there is an easy (but ugly) workaround - you just need to make the glob start before any potentially missing stuff:

gulp.src('{lib,__IGNORE_MISSING}/*.jar, { allowEmpty: true, base: 'lib' });

__IGNORE_MISSING in my example is just a random constant that does not match any potential file or directory.

XCompWiz commented 5 months ago

I spent a day tracking this down. Glad there's already a report for it.

I delved a bit, and the specific location I could get to was onAction calls fs.readdir and then onReadDir will return cp(err) with the "ENOENT: no such file or directory, scandir " error.

I think pavelhoral's solution is to a different problem, as I applied it locally and it did not solve our specific case.

For ours, I think it would be important to check if the path exists before trying to walk it. The base of globs is assumed to exist. This was not previously the case in 7.0.0 or earlier.

Not throwing the error in onReaddir, in the same way onStat ignores any errors, would likely work very easily, but I'm uncertain if there could be other errors that would be important to catch, such as when reading through symlinks or drive permission issues.

A more robust solution would be to add a "prewalk" action which stats the path, ignores errors with empty callback, and queues the walk action on the path in any other case.