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

ERROR uncaughtException: Cannot read property 'aborted' of null #1229

Closed
d4rkstar opened this issue Nov 2, 2017 · 12 comments
Closed

ERROR uncaughtException: Cannot read property 'aborted' of null #1229

d4rkstar opened this issue Nov 2, 2017 · 12 comments

Comments

@d4rkstar
Copy link

d4rkstar commented Nov 2, 2017

if (this._req.aborted) return;

It seems that, if a previous error occurs, this._req is null. So this line seems to produce an exception.

@lpinca
Copy link
Member

lpinca commented Nov 2, 2017

See #1201, is there a way to reproduce the issue?

@lpinca
Copy link
Member

lpinca commented Nov 2, 2017

Are you by any chance throwing an error from the 'error' listener and using process.once('uncaughtException')?

This is the only way I can make http.ClientRequest emit the 'error' event twice on Node.js 8:

const http = require('http');

const host = 'a'.repeat(10);
let req = http.get({ host });

req.on('error', (err) => {
  if (req.aborted) return;
  req = null;
  throw err;
});

process.once('uncaughtException', () => {});

Can you also please add more details?

  • What is the Node.js version?
  • What is the ws version?
  • What is the OS?
  • Are you using SSL?

Thanks.

@d4rkstar
Copy link
Author

d4rkstar commented Nov 2, 2017

Hello Luigi,
thank you for your feedback. Fortunately i've logs about the error :)

Before, i'll give you more informations about my environment:

Using webstomp over websocket with SSL:

let stomp_url = 'wss://remotehost:8443/ws';
self.client = webstomp.over(new WebSocket(stomp_url), options);

The trace:

2017-10-24T09:33:14.779Z ERROR uncaughtException: connect ECONNREFUSED xxx.xxx.xxx.xxx:8443
        {"date":"Tue Oct 24 2017 11:33:14 GMT+0200 (CEST)","process":{"pid":23454,"uid":1001,"gid":1001,"cwd":"/home/myapp/myapp","execPath":"/usr/bin/node","version":"v8.6.0","argv":["/usr/bin/node","/home/myapp/myapp/www"],"memoryUsage":{"rss":91394048,"heapTotal":51220480,"heapUsed":38065344,"external":239175}},"os":{"loadavg":[0,0,0],"uptime":1794013},"trace":[{"column":11,"file":"util.js","function":"Object._errnoException","line":1019,"method":"_errnoException","native":false},{"column":20,"file":"util.js","function":"_exceptionWithHostPort","line":1041,"method":null,"native":false},{"column":14,"file":"net.js","function":"TCPConnectWrap.afterConnect [as oncomplete]","line":1175,"method":"afterConnect [as oncomplete]","native":false}],"stack":["Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:8443","    at Object._errnoException (util.js:1019:11)","    at _exceptionWithHostPort (util.js:1041:20)","    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1175:14)"]}

Regards

@lpinca
Copy link
Member

lpinca commented Nov 2, 2017

Thanks, that seems a different error though (not the one in the issue title) and it isn't caught because you didn't add an 'error' listener to the WebSocket instance.

@lpinca
Copy link
Member

lpinca commented Nov 2, 2017

Ok, I can reproduce with this code:

const WebSocket = require('ws');

const ws = new WebSocket('wss://localhost');

process.on('uncaughtException', (err) => {
  console.error(err);
});
$ node index.js
{ Error: connect ECONNREFUSED 127.0.0.1:443
    at Object._errnoException (util.js:1021:11)
    at _exceptionWithHostPort (util.js:1043:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1175:14)
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 443 }
TypeError: Cannot read property 'aborted' of null
    at ClientRequest._req.on (/home/luigi/1229/node_modules/ws/lib/WebSocket.js:646:19)
    at emitOne (events.js:115:13)
    at ClientRequest.emit (events.js:210:7)
    at TLSSocket.socketCloseListener (_http_client.js:361:9)
    at emitOne (events.js:120:20)
    at TLSSocket.emit (events.js:210:7)
    at _handle.close (net.js:547:12)
    at TCP.done [as _onclose] (_tls_wrap.js:356:7)

but this is not an issue in ws.

The problem here is the use of 'uncaughtException'. We are emitting an 'error' event here and if there are no listeners the error is thrown. The 'uncaughtException' listener prevents the process from exiting. The thrown error prevents this flag from being set and for this reason a second 'error' event is emitted.

This no longer happens in Node.js 9 (nodejs/node@620ba41694) but there is nothing wrong also in previous versions of Node.js. 'uncaughtException' should not be used.

@d4rkstar
Copy link
Author

d4rkstar commented Nov 2, 2017

Thank you again Luigi. Will change my code and will update or close this issue

@lpinca
Copy link
Member

lpinca commented Nov 13, 2017

Any update here?

@lpinca
Copy link
Member

lpinca commented Nov 20, 2017

Closing due to inactivity. If your issue is still unresolved, please comment back and I will reopen this.

@derwaldgeist
Copy link

Having the same problem here when using ws in Electron.

@damianobarbati
Copy link

same here with electron!

@ghost
Copy link

ghost commented Dec 5, 2018

Having the problem since I switched to the very first version in which you support handshakeTimeout (something around 3.0.2 or so)

From this version on up to the latest: If this sequence goes into "error", I'll receive an exception

TypeError: Cannot read property 'setHeader' of null

a couple of seconds after the error occurs. The first attempt fails as expected after 5s

Error: Opening handshake has timed out

If I repeat the sequence then, it immediately fails with

Error: connect EHOSTDOWN 192.168.188.98:8888 - Local (192.168.188.24:57769)

but then after 5 s the exception occurs. For me it looks like as if you would not terminate the handshakeTimer on error

     let server = new ws(argv.ws_uri, {handshakeTimeout: 5000})
         server.on('open', () => {
             server.send(JSON.stringify({
                 id: 1,
                 method: "ping",
                 params: {
                   interval: 3000
                 },
                 jsonrpc: "2.0"
             }))
         })
         server.on('message', (data) => {
             console.log(data)
             res.send("OK")
         })
         server.on('error', (error) => {
             console.log(error)

             res.send("ERROR "+error)
         })

@lpinca
Copy link
Member

lpinca commented Dec 5, 2018

@accuware your issue is different from the one reported by the original poster. In your case it seems that

abortHandshake(this, req, 'Opening handshake has timed out')

is called after the 'error' or the 'upgrade' event is emitted on the req object which would be a bug in Node.js. Are you able to create a reproducible test case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants