gulpjs / gulpjs/gulp

Pipeline errors are not properly handled in Gulp v5

Open
#2,812 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
32.9k
Forks
4.1k
PR merge metrics
No merged PRs in 30d

Description

Before you open this issue, please complete the following tasks:

* [x] use the search bar at the top of the page to search this repository for similar issues or discussions that have already been opened.
* [ ] if you are looking for help from the gulp team or community, open a [discussion](https://github.com/gulpjs/gulp/discussions).
* [ ] if you think there is a problem with the plugin you're using, open a [discussion](https://github.com/gulpjs/gulp/discussions).
* [x] if you think there is a bug in our code, open this issue.

### What were you expecting to happen?

When using `gulp.src(...).pipe(stream).pipe(secondStream)`, any `stream` error should be shown by Gulp and complete the task (marking it as failed).

### What actually happened?

`stream` errors in the pipeline are not shown by Gulp, and the task is shown as incomplete.

### Please give us a sample of your gulpfile

```js
// gulpfile.js
import gulp from 'gulp'
import {Transform, PassThrough} from 'node:stream'

export default () => gulp
.src('./gulpfile.js')
.pipe(new Transform({
transform(file, encoding, done) {
done(new Error('example'))
},
objectMode: true,
}))
.pipe(new PassThrough({objectMode: true}))
```

### Terminal output / screenshots

With Gulp v5:

```
$ gulp
[01:46:48] Using gulpfile ~/Desktop/gulpfile.js
[01:46:48] Starting 'default'...
[01:46:48] The following tasks did not complete: default
Did you forget to signal async completion?
```

With Gulp v4, this worked correctly:

```
$ gulp
[01:45:39] Using gulpfile ~/Desktop/gulpfile.js
[01:45:39] Starting 'default'...
[01:45:39] 'default' errored after 15 ms
[01:45:39] Error: example
at Transform.transform [as _transform] (file:///.../Desktop/gulpfile.js:8:12)
at Transform._write (node:internal/streams/transform:171:8)
at writeOrBuffer (node:internal/streams/writable:564:12)
at _write (node:internal/streams/writable:493:10)
at Writable.write (node:internal/streams/writable:502:10)
at DestroyableTransform.ondata (/.../Desktop/node_modules/to-through/node_modules/readable-stream/lib/_stream_readable.js:619:20)
at DestroyableTransform.emit (node:events:520:28)
at DestroyableTransform.emit (node:domain:551:15)
at addChunk (/.../Desktop/node_modules/to-through/node_modules/readable-stream/lib/_stream_readable.js:291:12)
at readableAddChunk (/.../Desktop/node_modules/to-through/node_modules/readable-stream/lib/_stream_readable.js:278:11)
```

### Please provide the following information:
* OS & version [e.g. MacOS Catalina 10.15.4]: Ubuntu 24.04
* node version (run `node -v`): 22.3.0
* npm version (run `npm -v`): 10.8.1
* gulp version (run `gulp -v`): 5.0.0

### Additional information

This bug only happens when the stream that errors is not the last line in the pipeline. This means `.pipe()` must be called more than once.

It seems like this bug is related to `vinyl-fs` (https://github.com/gulpjs/vinyl-fs/pull/333 by @sttk) and `to-through` (https://github.com/gulpjs/to-through/pull/9 by @coreyfarrell) switching to `streamx`. The problem seems to be happening inside `async-done`, specifically the following line:

https://github.com/gulpjs/async-done/blob/4a7efae92c90ae6358412f2dc759561f0cb94ccc/index.js#L31

What seems to be happening is:
- A stream in the pipeline errors
- This calls `stream.destroy(error)`
- Which itself calls `stream.emit('error', error)`
- However, for some reason, in Gulp v5 (not Gulp v4), the `error` event is not properly triggered on `domain`, which means `async-done` never completes.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.