got: Regression handling multiple request errors

Describe the bug

  • Node.js version: 10, 12, 14
  • OS & version: macOS 10.15.4

Starting with v11.0, emitting more than one error on the ClientRequest causes an unhandled error event.

Code to reproduce

got('http://example.com')
  .on('request', req => {
    req.once('socket', () => {
      req.emit('error', new Error("foo bar 1"))
      req.emit('error', new Error("foo bar 2"))
    })
  })
  .catch(reason => {
    console.log('caught', reason.message)
  })

Actual behavior

    throw er; // Unhandled 'error' event
    ^

Error: foo bar 2
    ...

Expected behavior

Previous behavior was to reject the promise with the first error, but each subsequent error would still run through the beforeError hook and propagate the event. Not sure if that is the right behavior, but it probably is. Regardless, looking at the changelog, this new behavior seems to be an unintended change.

I’m sure @szmarczak will know off hand, but this seems to have been caused by the “Rewrite Got” aligning on using request.once instead of using request.on in request-as-event-emitter.ts.

One thing to note about the ‘code to reproduce’ above is that the errors are emitted between the socket and response events. This was identified because it broke Nock’s test suite when upgrading to Got 11. https://github.com/nock/nock/issues/1992 Nock emits the “Nock: No match for request” error between those two events, Got then calls abort on the ClientRequest which emits a “socket hang up” error. The same behavior can seen with the ‘code to reproduce’ by commented out the second call to emit.

Checklist

  • I have read the documentation.
  • I have tried my code with the latest version of Node.js and Got.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 16 (6 by maintainers)

Most upvoted comments

Thanks for your time @ronag

If destroy is preferred over emitting an error on ClientRequest, why are conn reset errors emitted? (example )

Because Node has a lot of old code which is not trivial to re-write to use pragmatic streams. It should use destroy(err) but we haven’t yet managed to refactor this part of the code. It is work in progress.

If you look at the changlog for v13 and v14 we have fixed a lot of these cases in core and are working to sort out even more.