Skip to content

stream.pipeline(httpResponse, decompressStream) emits error three times #31029

Closed
@szmarczak

Description

  • Version: v13.5.0
  • Platform: Linux solus 5.4.1-137.current #1 SMP PREEMPT Sat Dec 7 15:17:22 UTC 2019 x86_64 GNU/Linux
  • Subsystem: stream, http
const http = require('http');
const {pipeline, PassThrough} = require('stream');

http.get('http://example.com', response => {
	const stream = new PassThrough();

	stream.on('error', error => {
		console.log('stream error', error);
	});

	pipeline(
		response,
		stream,
		error => {
			console.log('pipeline error', error);
		}
	);

	stream.destroy(new Error('oh no'));
}).on('error', error => {
	console.log('request error', error);
});

If you run the example above, the error will be emitted three times:

  • stream error (oh no)
  • pipeline error (oh no)
  • request error (oh no)

I did not expect the ClientRequest instance to throw.
It's because response.destroy(error) calls socket.destroy(error) directly.
ClientRequest catches the error and throws it again.

But why does it call response.destroy(error)?
Well, it happens because of 6480882 (previously it just called response.destroy()).

If you run the example in Node.js 12, you will get these results:

  • stream error (Cannot call write after a stream was destroyed)
  • pipeline error (Cannot call write after a stream was destroyed)
  • stream error (oh no)

I just want to say that the new behavior is correct, but ClientRequest should not throw if using pipeline with response.

Metadata

Assignees

No one assigned

    Labels

    httpIssues or PRs related to the http subsystem.streamIssues and PRs related to the stream subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions