Skip to content

Add option for gulp.watch to ignore task errors #216

Description

@th0r

I have this styles.app task to compile my *.styl files:

gulp.task('styles.app', function () {
    return gulp
        .src('app/client/styles/*.styl')
        .pipe(stylus({
            use: ['nib'],
            set: util.env.production ? null : ['firebug', 'linenos']
        }))
        .pipe(gulpif(util.env.production, csso()))
        .pipe(gulp.dest('public/css/app'));
});

If there is some kind of error during styles compilation, gulp-stylus plugin 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.watch to recompile styles "on the fly":

gulp.watch('app/client/styles/**/*.styl', ['styles.app']);

...and I don't want it to fail on any error in styles.app task.
Is there any way to do it?

Activity

  1. escapedcat commented on Jan 29, 2014

    @escapedcat

    Haven't used it, but I think https://github.com/floatdrop/gulp-plumber can help with this.

  2. th0r commented on Jan 29, 2014

    @th0r
    Author

    As I understand, gulp-plumber can help reduce the number of .on('error', ...) handlers, but I can't see how it can help in my case.

  3. escapedcat commented on Jan 29, 2014

    @escapedcat

    Hm, I saw this and thught that's your case as well:
    http://markgoodyear.com/2014/01/getting-started-with-gulp/#comment-1214181355

    I thought you can use it, so even if styles.app throws an error it continues watching. Maybe I got you wrong.

  4. PavelGavlik commented on Jan 29, 2014

    @PavelGavlik

    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?

  5. phated commented on Jan 29, 2014

    @phated
    Member

    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.

  6. yocontra commented on Jan 30, 2014

    @yocontra
    Member

    Use multipipe

  7. PavelGavlik commented on Jan 30, 2014

    @PavelGavlik

    @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.

  8. th0r commented on Jan 30, 2014

    @th0r
    Author

    Use multipipe

    To handle compile error? I can do it without multipipe like 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 in gulp.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".

  9. yocontra commented on Jan 30, 2014

    @yocontra
    Member

    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.

  10. th0r commented on Jan 30, 2014

    @th0r
    Author

    All my attempts to make what I want have failed.
    @contra, please, can you write the whole snippet which satisfies these two conditions:

    1. Execution of gulp styles from console fails on compilation error (exits with non-zero code)
    2. gulp.watch('*.styl', ['styles']) not fails on compilation errors, but just logs it.
  11. PavelGavlik commented on Jan 30, 2014

    @PavelGavlik

    @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);
    });
    
  12. r3mi commented on Feb 7, 2014

    @r3mi

    I am trying this kind of pattern, so it fails from console gulp build and just log errors when watching gulp watch

    var 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 ?

  13. yocontra commented on Feb 7, 2014

    @yocontra
    Member

    @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 watching variable

    Also please don't mention "just logs errors" off-hand. We need to see the errors, code you used that made them, etc.

  14. sidwood commented on Feb 7, 2014

    @sidwood

    I would prefer to use multipipe over plumber but nothing seems to emit an end event, 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();
    });
  15. 23 remaining items

  16. mnpenner commented on Mar 11, 2015

    @mnpenner

    @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?

  17. mnpenner commented on Mar 11, 2015

    @mnpenner

    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.

  18. kirkstrobeck commented on Mar 11, 2015

    @kirkstrobeck
  19. LePetitDev commented on Mar 16, 2015

    @LePetitDev
  20. gronke commented on May 4, 2015

    @gronke
  21. guategeek commented on May 8, 2015

    @guategeek

    Thank you so much guys for figuring this out!

  22. ndbroadbent commented on Jul 8, 2015

    @ndbroadbent

    @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 gulp command 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 during watch, and crash normally otherwise.

    On the other hand, it's very annoying that I need to restart gulp watch whenever I have a syntax error in my source files. I could use until gulp watch; do; sleep 1; done, but it's not the best solution.

    @contra - I'm running gulp 3.9.0, and my gulp.watch task 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
    
  23. yocontra commented on Jul 9, 2015

    @yocontra
    Member

    @ndbroadbent You are still having the problem because this was fixed in 4.0 and you are using 3.9

  24. mnpenner commented on Jul 10, 2015

    @mnpenner

    @contra 4.0 doesn't appear to be out yet. npm doesn't even list a beta version. Will watch not crash by default, or do we need to pass it some options?

  25. TheunisKotze commented on Oct 26, 2015

    @TheunisKotze

    @contra @mnpenner I'd also like to know ^

  26. callumacrae commented on Oct 26, 2015

    @callumacrae
    Member

    @mnpenner @TheunisKotze You can install gulp from github to get gulp 4.0. npm install gulpjs/gulp#4.0

  27. TheunisKotze commented on Oct 26, 2015

    @TheunisKotze

    @callumacrae thanks, thought the question I meant was:

    Will watch not crash by default, or do we need to pass it some options?

  28. hatashiro commented on Nov 30, 2015

    @hatashiro

    Same point with @ndbroadbent. I may just go with @r3mi 's solution until Gulp 4.0 is coming out.

  29. locked and limited conversation to collaborators on Nov 30, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions