Repository navigation
Add option for gulp.watch to ignore task errors #216
Description
Activity
Haven't used it, but I think https://github.com/floatdrop/gulp-plumber can help with this.
As I understand,
gulp-plumbercan help reduce the number of.on('error', ...)handlers, but I can't see how it can help in my case.Hm, I saw this and thught that's your case as well:
http://markgoodyear.com/2014/01/getting-started-with-gulp/#comment-1214181355I thought you can use it, so even if styles.app throws an error it continues watching. Maybe I got you wrong.
I am trying to setup Gulp, so it displays any errors that plugins throw and then continues watching files. I tried gulp-plumber which displays the error, but task that caused the error is not run on next file change. I also tried combining-streams-to-handle-errors recipe from docs, but it doesn't work with current gulp-util.
Is there currently a way to catch and display errors and keep running Gulp forever?I would avoid gulp-plumber. But you can use something like multipipe or domains to catch and handle the errors, that will keep your process from crashing. I also made a silly example that shows domain usage.
Let me know if those help you at all.
Use multipipe
@phated Nice example, thanks. Unfortunately, it doesn't solve my problem. I made a simplified example of what I'm trying to achieve: https://gist.github.com/PavelGavlik/8ddf07d71b99dcd324e0/991a9b8dfd51f6dc436ab087010748d03c5f1080 I need the 'index' task to run after both 'script' and 'styles' task are complete. It works exactly like my solution using plumber - task that causes the error is not run on next file change. It looks like 'styles' task hangs and 'index' task is never launched because of hanging 'styles' task.
@contra I also tried using multipipe like this: https://gist.github.com/PavelGavlik/8ddf07d71b99dcd324e0 , but it has same behavior as solution using domains.Do you have any idea how to solve this? I have been unable to google something that would help me.
Use multipipe
To handle compile error? I can do it without
multipipelike this:gulp.task('styles.app', function () { return gulp .src('app/client/styles/*.styl') .pipe(stylus({ use: ['nib'], set: util.env.production ? null : ['firebug', 'linenos'] })) .on('error', gutil.log) .pipe(gulpif(util.env.production, csso())) .pipe(gulp.dest('public/css/app')); });But it will suppress the error and
gulp styles.app && echo 'OK!'will print "ok", but it's not.
The question is how to ignore this error ingulp.watch?
I could do something like this:gulp.watch('app/client/styles/**/*.styl', function() { return gulp .src('app/client/styles/*.styl') .pipe(stylus()) .on('error', gutil.log) .pipe(gulp.dest('public/css/app')); });...but I don't like "copy/paste".
The problem here is that orchestrator listens for the error event on the returned stream when you use that format. When it sees an error, it marks the task as errored and kills the chain. Just use the callback format instead if you don't want that behavior.
gulp.task('styles', ['dist-clean'], function(cb) { var combined = multipipe( gulp.src('*.less'), less(), rev(), gulp.dest('dist') ); combined.on('error', errorHandler); combined.on('end', cb); });
Failing the task on an error seems like the most common use case. If you want to define what failed is yourself you can use the callback pattern to give you more control.
All my attempts to make what I want have failed.
@contra, please, can you write the whole snippet which satisfies these two conditions:- Execution of
gulp stylesfrom console fails on compilation error (exits with non-zero code) gulp.watch('*.styl', ['styles'])not fails on compilation errors, but just logs it.
- Execution of
@contra Thanks for help. It didn't work exactly as I needed, but in the end I solved it like this:
gulp.task('styles', ['dist-clean'], function(cb) { gulp.src('*.less') .pipe(plumber()) .pipe(less()) .pipe(rev()) .pipe(gulp.dest('dist')) .on('end', cb); });I am trying this kind of pattern, so it fails from console
gulp buildand just log errors when watchinggulp watchvar watching = false; gulp.task('watch', ['build'], function() { watching = true; gulp.watch(["templates/*"], ['build']); }); gulp.task('build', function() { return gulp.src('templates/*') .pipe(watching ? plumber() : gutil.noop()) .pipe(template({pkg: pkg})) .pipe(gulp.dest('dist')); });
does it make sense ?
@r3mi What are you trying to do? If you are just trying to watch files and run a task when they change then I'm not sure where you picked up that
watchingvariableAlso please don't mention "just logs errors" off-hand. We need to see the errors, code you used that made them, etc.
I would prefer to use multipipe over plumber but nothing seems to emit an
endevent, so after a file change it just hangs. Currently, I'm just calling the callback which seems to work fine.gulp.task('styles', ['dist-clean'], function(cb) { multipipe( gulp.src('*.styl'), stylus(), gulp.dest('dist') ).on('error', errorHandler); cb(); });
23 remaining items
@PavelGavlik I just tried your 'solution' -- it doesn't seem to work. Plumber prints the error and then the watcher dies, as usual. Can you show how you set up the watcher?
I think I finally have a working solution, thanks to @kirkstrobeck and Kate Hudson !
Here's an example:
gulp.task('styles', function () { return gulp.src(styles, {base: '.'}) .pipe(plumber({ errorHandler: function(error) { gutil.log( gutil.colors.cyan('Plumber') + gutil.colors.red(' found unhandled error:\n'), error.toString() ); this.emit('end'); } })) .pipe(gulpif(/\.less$/,less({ strictMath: true, strictUnits: true, }))) // ... more pipes ... .pipe(plumber.stop()) .pipe(gulp.dest('www/css')) }); gulp.task('watch', function() { gulp.watch(['www/css/**/*.{css,less}','!www/css/main.css'], ['styles']); });
The error handler I copied out of the Plumber source which puts the pretty colors, then I added the
this.emit('end')bit from Kirk's link which solves the watcher crashing issue.+1 @k88hudson
Thank you so much guys for figuring this out!
@mnpenner - I'm sorry but your solution seems to have the same problem as above. When running the task outside of
watch, the error is swallowed and the process exits with a successful error code (0).I feel like there is some misunderstanding in this thread. One reason that we need the non-zero exit code is for when you're running a
gulpcommand in a CI environment, as a check to make sure that everything can be compiled without errors. In that case you want your build to fail, but if you swallow the errors with any of the solutions above, your CI service will assume that everything has passed. So we only want to ignore errors duringwatch, and crash normally otherwise.On the other hand, it's very annoying that I need to restart
gulp watchwhenever I have a syntax error in my source files. I could useuntil gulp watch; do; sleep 1; done, but it's not the best solution.@contra - I'm running gulp
3.9.0, and mygulp.watchtask is still crashing on errors.@r3mi - Thanks, your workaround is the only one that worked for me so far (although it's a bit of a hack, and I have to add that line to every command that might throw an error.)
Finally, just to clarify the behaviour that we're looking for:
Inside
watch- handles any errors without crashing:$ gulp watch [15:52:01] Using gulpfile ~/code/example/gulpfile.js [15:52:01] Starting 'watch'... [15:52:01] Finished 'watch' after 32 ms [15:52:03] Starting 'styles'... [15:52:03] Starting 'templates'... [15:52:03] Finished 'templates' after 91 ms [15:52:03] Starting 'scripts'... [15:52:03] Finished 'styles' after 273 ms [15:52:03] Finished 'scripts' after 223 ms [15:52:03] Plumber found unhandled error: /Users/ndbroadbent/code/example/login.coffee:19:1: error: unmatched } } ^ [15:52:10] Starting 'styles'... [15:52:10] Starting 'templates'... [15:52:10] Finished 'templates' after 18 ms [15:52:10] Starting 'scripts'... [15:52:10] Starting 'templates'... [15:52:10] Finished 'styles' after 133 ms [15:52:10] Finished 'scripts' after 128 ms [15:52:10] Finished 'templates' after 140 ms [15:52:10] Plumber found unhandled error: /Users/ndbroadbent/code/example/login.coffee:19:1: error: unmatched } } ^Outside
watch- Crashes with error and non-zero exit code:$ gulp scripts [15:54:26] Using gulpfile ~/code/example/gulpfile.js [15:54:26] Starting 'templates'... [15:54:26] Finished 'templates' after 74 ms [15:54:26] Starting 'scripts'... [15:54:27] Finished 'scripts' after 160 ms events.js:85 throw er; // Unhandled 'error' event ^ /Users/ndbroadbent/code/example/login.coffee:19:1: error: unmatched } } ^ $ echo $? 1@ndbroadbent You are still having the problem because this was fixed in 4.0 and you are using 3.9
@contra 4.0 doesn't appear to be out yet. npm doesn't even list a beta version. Will
watchnot crash by default, or do we need to pass it some options?@mnpenner @TheunisKotze You can install gulp from github to get gulp 4.0.
npm install gulpjs/gulp#4.0@callumacrae thanks, thought the question I meant was:
Will watch not crash by default, or do we need to pass it some options?
Same point with @ndbroadbent. I may just go with @r3mi 's solution until Gulp 4.0 is coming out.
- locked and limited conversation to collaborators
on Nov 30, 2015
I have this
styles.apptask to compile my*.stylfiles:If there is some kind of error during styles compilation,
gulp-stylusplugin throws an error...and it's ok, because I want build process to exit with non-zero code when building for production.But for development I use
gulp.watchto recompile styles "on the fly":...and I don't want it to fail on any error in
styles.apptask.Is there any way to do it?