Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Error management in gulp

#Error management in gulp

Sucking at something is the first step to becoming sorta good at something

No one can assure you, that plugins will run smooth in any circumstances (except for tests - they could), so neither should you convince anyone, that your plugin will never break. Only thing, that you could possibly do (if something gone wrong) - is gracefully inform your plugin user, that something went wrong and die.

We are will use this plugin from beginning to demonstrate error management. Suppose you have a task in gulpfile.js that contains this code (we modified it a little bit to be closer to real-usage):

var coffee = require('gulp-coffee');

gulp.src('coffee/**/*.coffee')
  .pipe(gulpPrefixer('// Copyright 2014 (C) Aswesome company'))
  .pipe(coffee())
  .pipe(gulp.dest('js/'));

What could possibly go wrong? Well gulpPrefixer could emit errors event, as any of Stream gulp-plugins, for example gulp-sass. If you don't do anything with it inside task, Node will throw errors and whole task will be stopped.

You can easily avoid it by catch them and show by appending .on('error', gutil.log) handlers:

gulp.src('coffee/**/*.coffee')
  .pipe(gulpPrefixer('// Copyright 2014 (C) Aswesome company'))
  .on('error', gutil.log)
  .pipe(coffee())
  .on('error', gutil.log)
  .pipe(gulp.dest('js/'));

But this will not solve "stopping" problem of the task. By design, Node stream will stop accepting incoming data, if error event was raised. You can see it in stream.js:103 - cleanup function will deattach ondata handler from source (which in our case is gulp.src) and coffee plugin will stop receiving files although, the rest of the files can be compiled.

For now, we have no other solution besides patching pipe function behaviour. So the gulp-plumber may fix this problem:

gulp.src('coffee/**/*.coffee')
  .pipe(plumber())
  .pipe(gulpPrefixer('// Copyright 2014 (C) Aswesome company'))
  .pipe(coffee())
  .pipe(gulp.dest('js/'));

Note: This will work only if Stream class used in gulp-plugin will not panic on error event and stop being writable/readable.

@felixrabe

This comment has been minimized.

Show comment
Hide comment
@felixrabe

felixrabe Jun 11, 2014

Non-master permalink for stream.js: stream.js:103

Non-master permalink for stream.js: stream.js:103

@barneycarroll

This comment has been minimized.

Show comment
Hide comment
@barneycarroll

barneycarroll Jul 13, 2014

Once you've decided to adopt plumber, you pretty much want it invoked whenever you open a gulp pipe chain. Why not have a DRY convenience wrapper, e.g.:

gulp.plumbedSrc = function( src ){
  return gulp.src.call( gulp, Array.prototype.slice( arguments, 0 ) )
    .pipe( plumber() );
}

Once you've decided to adopt plumber, you pretty much want it invoked whenever you open a gulp pipe chain. Why not have a DRY convenience wrapper, e.g.:

gulp.plumbedSrc = function( src ){
  return gulp.src.call( gulp, Array.prototype.slice( arguments, 0 ) )
    .pipe( plumber() );
}
@timnew

This comment has been minimized.

Show comment
Hide comment
@timnew

timnew Jul 14, 2014

@barneycarroll

I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.apply( gulp, Array.prototype.slice( arguments, 0 ) )
    .pipe( plumber() );
}

timnew commented Jul 14, 2014

@barneycarroll

I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.apply( gulp, Array.prototype.slice( arguments, 0 ) )
    .pipe( plumber() );
}
@hontas

This comment has been minimized.

Show comment
Hide comment
@hontas

hontas Oct 16, 2014

@barneycarroll
@timnew

And I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.apply( gulp, Array.prototype.slice.call( arguments ))
    .pipe( plumber() );
}

hontas commented Oct 16, 2014

@barneycarroll
@timnew

And I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.apply( gulp, Array.prototype.slice.call( arguments ))
    .pipe( plumber() );
}
@radekn

This comment has been minimized.

Show comment
Hide comment
@radekn

radekn Nov 27, 2014

@barneycarroll
@timnew
@hontas

I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.apply( gulp, arguments )
    .pipe( plumber() );
}

radekn commented Nov 27, 2014

@barneycarroll
@timnew
@hontas

I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.apply( gulp, arguments )
    .pipe( plumber() );
}
@vmadman

This comment has been minimized.

Show comment
Hide comment
@vmadman

vmadman Dec 22, 2014

@barneycarroll
@timnew
@hontas
@radekn

I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.raawwwrrrrrrr();  // todo: define raawwwrrrrrrr()
}

vmadman commented Dec 22, 2014

@barneycarroll
@timnew
@hontas
@radekn

I assume you mean this:

gulp.plumbedSrc = function( ){
  return gulp.src.raawwwrrrrrrr();  // todo: define raawwwrrrrrrr()
}
@scharf

This comment has been minimized.

Show comment
Hide comment
@scharf

scharf Jan 9, 2015

What about the solution proposed Joel Rich here and here? The idea is to patch gulp.src.

scharf commented Jan 9, 2015

What about the solution proposed Joel Rich here and here? The idea is to patch gulp.src.

@sandro-pasquali

This comment has been minimized.

Show comment
Hide comment
@sandro-pasquali

sandro-pasquali Apr 7, 2015

I found overriding #src and binding to gulp-notify to be pretty simple and useful

var _gulpsrc = gulp.src;
gulp.src = function() {
    return _gulpsrc.apply(gulp, arguments)
    .pipe(plumber({
        errorHandler: function(err) {
            notify.onError({
                title:    "Gulp Error",
                message:  "Error: <%= error.message %>",
                sound:    "Bottle"
            })(err);
            this.emit('end');
        }
    }));
};

I found overriding #src and binding to gulp-notify to be pretty simple and useful

var _gulpsrc = gulp.src;
gulp.src = function() {
    return _gulpsrc.apply(gulp, arguments)
    .pipe(plumber({
        errorHandler: function(err) {
            notify.onError({
                title:    "Gulp Error",
                message:  "Error: <%= error.message %>",
                sound:    "Bottle"
            })(err);
            this.emit('end');
        }
    }));
};
@MiguelCastillo

This comment has been minimized.

Show comment
Hide comment
@MiguelCastillo

MiguelCastillo Apr 13, 2015

Alright, I had to add a useless comment... But the whole assumption/correction segment was pretty funny :D

Alright, I had to add a useless comment... But the whole assumption/correction segment was pretty funny :D

@brendanfalkowski

This comment has been minimized.

Show comment
Hide comment
@brendanfalkowski

brendanfalkowski May 1, 2015

I've been trying to wrap my head around error reporting. Anyone smarter than me have a better approach than this: mikaelbr/gulp-notify#81

Tried everything I could read up, but still not smooth. Feels like I'm missing something obvious nobody talks about anymore.

I've been trying to wrap my head around error reporting. Anyone smarter than me have a better approach than this: mikaelbr/gulp-notify#81

Tried everything I could read up, but still not smooth. Feels like I'm missing something obvious nobody talks about anymore.

@ckapilla

This comment has been minimized.

Show comment
Hide comment
@ckapilla

ckapilla Jul 21, 2015

@brendanfalkowski

Feels like I'm missing something obvious nobody talks about anymore.

story of my life

@brendanfalkowski

Feels like I'm missing something obvious nobody talks about anymore.

story of my life

@jiuxiaosheng

This comment has been minimized.

Show comment
Hide comment
@jiuxiaosheng

jiuxiaosheng Jan 5, 2016

i just want to say, it's funny to watch you guys talk;

i just want to say, it's funny to watch you guys talk;

@JonCatmull

This comment has been minimized.

Show comment
Hide comment
@JonCatmull

JonCatmull Feb 25, 2016

Haha great comment stream! and the article wasn't to bad either. 👍

Haha great comment stream! and the article wasn't to bad either. 👍

@wumble

This comment has been minimized.

Show comment
Hide comment

wumble commented Mar 16, 2016

great idea @sandro-pasquali

@demonkoryu

This comment has been minimized.

Show comment
Hide comment
@demonkoryu

demonkoryu Mar 17, 2016

Good article, but the comments... I can't even

Good article, but the comments... I can't even

@blackcater

This comment has been minimized.

Show comment
Hide comment
@blackcater

blackcater Mar 22, 2016

Thanks a lot!

Thanks a lot!

@kilianc

This comment has been minimized.

Show comment
Hide comment
@kilianc

kilianc Apr 13, 2016

This is very helpful for development but how do you handle CI and deploy? I need a hard exit > 0 if anything goes wrong.

kilianc commented Apr 13, 2016

This is very helpful for development but how do you handle CI and deploy? I need a hard exit > 0 if anything goes wrong.

@robianmcd

This comment has been minimized.

Show comment
Hide comment
@robianmcd

robianmcd Jun 14, 2016

@kilianc I'm setting a boolean to determine weather a task should exit the process or not and running something like this

var exitOnError = true; //set to false when running a watch task

//...
.pipe(somethingThatThrowsAnError())
.on("error", function (err) {
  gutil.log(err);
  if(exitOnError) {
    process.exit(1);
  } else {
    this.emit('end');
  }
});

...seems kind of crazy there is no standard way to do this in gulp

robianmcd commented Jun 14, 2016

@kilianc I'm setting a boolean to determine weather a task should exit the process or not and running something like this

var exitOnError = true; //set to false when running a watch task

//...
.pipe(somethingThatThrowsAnError())
.on("error", function (err) {
  gutil.log(err);
  if(exitOnError) {
    process.exit(1);
  } else {
    this.emit('end');
  }
});

...seems kind of crazy there is no standard way to do this in gulp

@bolemaxgit

This comment has been minimized.

Show comment
Hide comment
@bolemaxgit

bolemaxgit Jun 23, 2016

@robianmcd I hate just logging the entire error object, so I always just log err.message. It's way easier to read.

@robianmcd I hate just logging the entire error object, so I always just log err.message. It's way easier to read.

@FieryCod

This comment has been minimized.

Show comment
Hide comment
@FieryCod

FieryCod Aug 15, 2016

Do we really need gulp-plumber in 2016? It seems that the watch do not stops when the error is occurred. Tried several times and everything is working fine.

gulp.task('styles', function() {   
 return gulp.src('public/sass/*.scss')
   .pipe(sass(SassOptions).on('error', sass.logError))
   .pipe(gulp.dest('public/stylesheets'));
});

Do we really need gulp-plumber in 2016? It seems that the watch do not stops when the error is occurred. Tried several times and everything is working fine.

gulp.task('styles', function() {   
 return gulp.src('public/sass/*.scss')
   .pipe(sass(SassOptions).on('error', sass.logError))
   .pipe(gulp.dest('public/stylesheets'));
});
@normbr

This comment has been minimized.

Show comment
Hide comment
@normbr

normbr Sep 7, 2016

I think FieryCod has a good question...any thoughts...is plumber still needed?

normbr commented Sep 7, 2016

I think FieryCod has a good question...any thoughts...is plumber still needed?

@Gwenouille

This comment has been minimized.

Show comment
Hide comment
@Gwenouille

Gwenouille Nov 7, 2016

Hi guys,
Did someone here manage to have gulp work nicely with stylus ? I have set a small watch task with a pipe through stylus, autoprefixer and others, and it crashes altogether if stylus encounters a problem on compiling (like a bad indent).

Hi guys,
Did someone here manage to have gulp work nicely with stylus ? I have set a small watch task with a pipe through stylus, autoprefixer and others, and it crashes altogether if stylus encounters a problem on compiling (like a bad indent).

@toby-howell

This comment has been minimized.

Show comment
Hide comment
@toby-howell

toby-howell Dec 14, 2016

@barneycarroll
@timnew
@hontas
@radekn

I assume you mean this:

gulp.plumbedSrc = (...args) => gulp.src(...args).pipe(plumber());

@barneycarroll
@timnew
@hontas
@radekn

I assume you mean this:

gulp.plumbedSrc = (...args) => gulp.src(...args).pipe(plumber());
@absolux

This comment has been minimized.

Show comment
Hide comment
@absolux

absolux Mar 14, 2017

😆 😃

gulp.plumbed = () => gulp.src(...arguments).pipe(plumber())

absolux commented Mar 14, 2017

😆 😃

gulp.plumbed = () => gulp.src(...arguments).pipe(plumber())
@VinnyFonseca

This comment has been minimized.

Show comment
Hide comment
@VinnyFonseca

VinnyFonseca Mar 24, 2017

¯_(ツ)_/¯

@absolux

gulp.plmbd = () => gulp.src(...args).pipe(plumber())

¯_(ツ)_/¯

@absolux

gulp.plmbd = () => gulp.src(...args).pipe(plumber())
@sassy-ankit

This comment has been minimized.

Show comment
Hide comment
@sassy-ankit

sassy-ankit May 19, 2017

@FieryCod This is mid of 2017 and yes plumber is a go-away-error kind of tool. Many plugins, particularly gulp-sass throw@import error because file is not ready or unreadable. Whenever sass compiler complies SASS files, dont know how, but it takes more time in pipe and next command is already ready to read the file as soon as file is made but not closed. I know this may sound lame, but something like this happens when you try to compile sass, concatenate other css and minify them in a single function. In this case, plumber and wait() is a work-around to let things going.

sassy-ankit commented May 19, 2017

@FieryCod This is mid of 2017 and yes plumber is a go-away-error kind of tool. Many plugins, particularly gulp-sass throw@import error because file is not ready or unreadable. Whenever sass compiler complies SASS files, dont know how, but it takes more time in pipe and next command is already ready to read the file as soon as file is made but not closed. I know this may sound lame, but something like this happens when you try to compile sass, concatenate other css and minify them in a single function. In this case, plumber and wait() is a work-around to let things going.

@paraofheaven

This comment has been minimized.

Show comment
Hide comment
@paraofheaven

paraofheaven Jul 19, 2017

plumber can solve the pro,that's just what i need

plumber can solve the pro,that's just what i need

@Joelsz

This comment has been minimized.

Show comment
Hide comment
@Joelsz

Joelsz Jun 15, 2018

Thanks @sassy-ankit that cleared my way to use plumber for gulp-sass

Joelsz commented Jun 15, 2018

Thanks @sassy-ankit that cleared my way to use plumber for gulp-sass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment