Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running gulp tasks in sequence throws `Unhandled stream error in pipe`

Tags:

node.js

gulp

I have a gulp task as following :

gulp.task('build-files, function(cb) {
    runSequence('run-build-cmd',
        'delete-dest', 'copy-files',
        cb);
});

This task is running whenever something changed in a source folder as following :

gulp.watch(pathToSrcFolder, ['build-files']);

So this task runs 3 other gulp tasks in the specified order, the first one it runs a build command, the second one will delete a folder as following :

gulp.task('delete-dest', (cb) => {
    del([pathToDestFolder], {force: true});
    cb();
});

and the third one will copy files from a source into two destinations :

gulp.task('copy-files', () => {
    return gulp.src(pathToSrcFolder)
        .pipe(gulp.dest(pathToDestFolder))
        .pipe(gulp.dest(anotherPath));
});

Please notice that the pathToDestFolder is the same folder in both delete-source and copy-files commands.

The problem I had running this sequence, is this error:

internal/streams/legacy.js:59
      throw er; // Unhandled stream error in pipe.
      ^

Error: ENOENT: no such file or directory, chmod 'pathToDestFolder\path\to\some\file\file.ext'

I don't know why I'm getting this error.

And when I run the gulp delete-dest in cmd prompt (which will clear the pathToDestFolder) and then gulp copy-files (which will copy the source folder into two folders pathToDestFolder and anotherPath) it works as expected .

So I guess runSequence didn't work as expected ? if so, how can I solve this ?

Edit:

I tried to use rimraf instead of del, and all seems to work just fine, I know that rimraf is depricated, and it's better to use del instead, but why del in this case results in an exception ?

Edit 2:

Instead of using rimraf as a solution, I tried this solution:

gulp.task('delete-dest', (cb) => {
    del([pathToDestFolder], {force: true})
    .then(paths => {cb();});
});

And it worked like magic.

Why this worked instead ? I don't know !

If someone can clarify things I would be greatful.

like image 390
Renaud is Not Bill Gates Avatar asked Mar 13 '19 10:03

Renaud is Not Bill Gates


1 Answers

If you look here, you'll find that del returns a promise. It's an async method.

In your code, you call the cb() right after calling del(...), but before del actually finishes deleting the directory.

That's why you have to execute the callback after chaining with then:

gulp.task('delete-dest', (cb) => {
    del([pathToDestFolder], {force: true})
    .then(paths => {cb();});
});

And then your operations will run in the correct order.

The error you were getting before is the result of things being run in a weird order, leading to weird behavior. Gulp is trying to copy to a directory while the file system is deleting it, and that conflict leads to a file system error.


As an experiment, you can try running the synchronous version of del like so:

gulp.task('delete-dest', (cb) => {
    del.sync([pathToDestFolder], {force: true});
    cb();
});

See if that works (though you should prefer the async version).


As a side note, unless this is a feature of Gulp 4 though probably not, rather than calling a callback in your task, you can just return a promise like so:

gulp.task('delete-dest', () => {
    return del([pathToDestFolder], {force: true});
});

That will tell Gulp that your task is finished, and it can move on to the next.

like image 64
pushkin Avatar answered Nov 16 '22 00:11

pushkin