Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http2 unhandled error read ECONNRESET at TLSWrap.onStreamRead #45244

Open
tomklino opened this issue Oct 30, 2022 · 3 comments
Open

http2 unhandled error read ECONNRESET at TLSWrap.onStreamRead #45244

tomklino opened this issue Oct 30, 2022 · 3 comments
Labels
http2 Issues or PRs related to the http2 subsystem.

Comments

@tomklino
Copy link

Version

Node.js v18.8.0

Platform

Linux 5.4.0-1089-azure #94~18.04.1-Ubuntu SMP Fri Aug 5 12:34:50 UTC 2022 x86_64 Linux

Subsystem

http2

What steps will reproduce the bug?

Initialize an http2 server like so

const http2 = require('http2');
const server = http2.createSecureServer(certFiles);
server.on('error', (err) => console.error(err));
server.on('stream', async (stream, headers) => {
//...
    stream.on('error', (err) => {
      console.error("ERROR: HTTP2 STREAM ERROR", err);
      if(!stream.destroyed) {
        stream.respond({
          ':status': 400
        })
      }
    })
//...
})

Create a client connection and terminate it abruptly

This will crash the server with the following error:

node:events:491
      throw er; // Unhandled 'error' event
      ^

Error: read ECONNRESET
    at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20)
Emitted 'error' event on TLSSocket instance at:
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -104,
  code: 'ECONNRESET',
  syscall: 'read'
}

Node.js v18.8.0

How often does it reproduce? Is there a required condition?

Whenever a client connection is abruptly closed

What is the expected behavior?

I expect the error should be caught in one of the error catching blocks:

either:

server.on('error', (err) => console.error(err));

or:

    stream.on('error', (err) => {
      console.error("ERROR: HTTP2 STREAM ERROR", err);
      if(!stream.destroyed) {
        stream.respond({
          ':status': 400
        })
      }
    })

What do you see instead?

Node crashes with the error:

node:events:491
      throw er; // Unhandled 'error' event
      ^

Error: read ECONNRESET
    at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20)
Emitted 'error' event on TLSSocket instance at:
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -104,
  code: 'ECONNRESET',
  syscall: 'read'
}

Additional information

No response

@santigimeno
Copy link
Member

I've been trying to reproduce the issue with no luck. Can try to post a self contained test that reproduces the issue, or provide more specific instructions on how to reproduce it. Thanks

@santigimeno santigimeno added the http2 Issues or PRs related to the http2 subsystem. label Oct 31, 2022
@natewaddoups
Copy link

Perfectly accurate but unhelpful advice from another thread about ECONNRESET:

ECONNRESET means the peer closed the connection (i.e., a fact of life you simply need to deal with) and should be handled by adding 'error' event listeners in the right places.

The real issue here isn't the ECONNRESET. It's the fact that the error object does not contains enough information to identify the "right places" to add the needed listeners.

For example, this is the entire call stack for the one that periodically restarts my service:

Error: read ECONNRESET
    at TLSWrap.onStreamRead (node:internal/stream_base_commons:217:20)
    at TLSWrap.callbackTrampoline (node:internal/async_hooks:130:17)

I suspect that those worthless call stacks are not a nodejs problem, but rather a Javascript runtime problem. But whether or not that's the case, could nodejs do anything to make these call stacks useful?

For example, provide default error listeners that just log information about which listener caught the error before terminating the process. That would give us enough information to actually use the advice that I quoted above.

@rrlapointe
Copy link

With no stack trace in the exception, I have no idea where to catch this exception in my code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http2 Issues or PRs related to the http2 subsystem.
Projects
None yet
Development

No branches or pull requests

4 participants