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

Unhandled 'error' event: "WebSocket was closed before the connection was established" when client was connected and network goes down #7964

Closed
crycode-de opened this issue May 23, 2022 · 26 comments · Fixed by #7581

Comments

@crycode-de
Copy link

crycode-de commented May 23, 2022

Which package is this bug report for?

discord.js

Issue description

Steps to reproduce:

  1. Create a very simple bot like the code sample below
  2. Let the bot connect to discord
  3. Destroy the network/internet connection of the machine running the script (e.g. unplug the (virtual) network cable)
  4. Wait until the bot tries to reconnect
  5. See the app crashes on an unhandled 'error' event
Error: WebSocket was closed before the connection was established
    at WebSocket.close (/home/peter/tmp/node_modules/ws/lib/websocket.js:285:14)
    at WebSocketShard.destroy (/home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:728:27)
    at Timeout.<anonymous> (/home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:522:12)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)
Emitted 'error' event on WebSocket instance at:
    at emitErrorAndClose (/home/peter/tmp/node_modules/ws/lib/websocket.js:984:13)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

Full log: log.txt

There seams to be no way to handle the WebSocket error event.

Expected behavior would be, that discord.js keeps trying to reestablish the connection, or that there is some chance to handle the error.

Came up with this, as my internet connection was gone away and my application using discord.js crashed with the above error.

Code sample

const { Client, Intents } = require('discord.js');

const token = 'xxx';

async function main () {
  const client = new Client({
    intents: [
      Intents.FLAGS.GUILDS,
    ],
  });

  client.on('debug', console.debug);
  client.on('warn', console.warn);
  client.on('error', console.error);

  client.on('ready', () => console.log('ready'));

  await client.login(token);
}

main();

Package version

13.7.0

Node.js version

16.14.2

Operating system

Debian 10

Priority this issue should have

Medium (should be fixed soon)

Which partials do you have configured?

No Partials

Which gateway intents are you subscribing to?

Guilds

I have tested this issue on a development release

No response

@IxPrumxI
Copy link

i don't think you even replugged the network again as you didn't mention it, so why would this be a bug?

@crycode-de
Copy link
Author

crycode-de commented May 24, 2022

i don't think you even replugged the network again as you didn't mention it, so why would this be a bug?

That's right, but the application shouldn't crash with an unhandled 'error' event.
There seams to be no way to handle the WebSocket error. Even tried to handle the shardError event, but without success.

Expected behavior would be, that discord.js keeps trying to reestablish the connection, or that there is some chance to handle the error.

Edit: I've updated the description above.

@crycode-de crycode-de changed the title uncaught exception: "WebSocket was closed before the connection was established" when client was connected and network goes down Unhandled 'error' event: "WebSocket was closed before the connection was established" when client was connected and network goes down May 24, 2022
@kyranet
Copy link
Member

kyranet commented May 24, 2022

I must ask, are you able to reproduce this with v14?

We are attaching ws.onerror along other events, I also expanded your stack within ws's code to get a better look at what's happening:

And for reference, onclose should be all that's necessary:

@crycode-de
Copy link
Author

crycode-de commented May 24, 2022

Same error with v14 (14.0.0-dev.1653091711-fdeac9d)

Example code:

const { Client, GatewayIntentBits  } = require('discord.js');

const token = 'xxx';

async function main () {
  const client = new Client({
    intents: [
      GatewayIntentBits.Guilds,
    ],
  });

  client.on('debug', console.debug);
  client.on('warn', console.warn);
  client.on('error', console.error);

  client.on('ready', () => console.log('ready'));

  await client.login(token);
}

main();
Logs
Provided token: ODEzMzY0MzU0OTgzNjU3NDcy.YDOOlQ.***************************
Preparing to connect to the gateway...
[WS => Manager] Fetched Gateway Information
    URL: wss://gateway.discord.gg
    Recommended Shards: 1
[WS => Manager] Session Limit Information
    Total: 1000
    Remaining: 999
[WS => Manager] Spawning shards: 0
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 10
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CONNECTED] Took 212ms
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] Setting a heartbeat interval for 41250ms.
[WS => Shard 0] [IDENTIFY] Shard 0/1 with intents: 1
[WS => Shard 0] [READY] Session 0dc4eeb1d880cc8b1aab826876829531.
[WS => Shard 0] [ReadyHeartbeat] Sending a heartbeat.
[WS => Shard 0] Shard received all its guilds. Marking as fully ready.
ready
[WS => Shard 0] Heartbeat acknowledged, latency of 119ms.
[WS => Shard 0] [HeartbeatTimer] Sending a heartbeat.
[WS => Shard 0] Heartbeat acknowledged, latency of 122ms.
[WS => Shard 0] [HeartbeatTimer] Sending a heartbeat.
[WS => Shard 0] [HeartbeatTimer] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.
    Status          : 0
    Sequence        : 2
    Connection State: OPEN
[WS => Shard 0] [DESTROY]
    Close Code    : 4009
    Reset         : true
    Emit DESTROYED: true
[WS => Shard 0] Clearing the heartbeat interval.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 10
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CLOSED
[WS => Shard 0] Failed to connect to the gateway, requeueing...
[WS => Manager] Shard Queue Size: 1; continuing in 5 seconds...
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 10
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] Did not receive HELLO in time. Destroying and connecting again.
[WS => Shard 0] [DESTROY]
    Close Code    : 4009
    Reset         : true
    Emit DESTROYED: true
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CONNECTING
[WS => Shard 0] Shard was destroyed but no WebSocket connection was present! Reconnecting...
node:events:504
      throw er; // Unhandled 'error' event
      ^

Error: WebSocket was closed before the connection was established
    at WebSocket.close (/home/peter/tmp/node_modules/ws/lib/websocket.js:285:14)
    at WebSocketShard.destroy (/home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:731:27)
    at Timeout.<anonymous> (/home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:525:12)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)
Emitted 'error' event on WebSocket instance at:
    at emitErrorAndClose (/home/peter/tmp/node_modules/ws/lib/websocket.js:984:13)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

@kyranet
Copy link
Member

kyranet commented May 24, 2022

Yeah, I see the issue now, prior to calling this.connection.close, we are calling this line:

Which removes all the listeners:

this.connection.onopen = this.connection.onclose = this.connection.onerror = this.connection.onmessage = null;

And because we are closing while the WS is in a connecting state, it emits an abortion error:

https://github.com/websockets/ws/blob/a690791df31cede48e7bcbce9d56411483309246/lib/websocket.js#L283-L286 -> https://github.com/websockets/ws/blob/a690791df31cede48e7bcbce9d56411483309246/lib/websocket.js#L1031-L1056

At this line within the last function, ws.onerror would be called:

https://github.com/websockets/ws/blob/a690791df31cede48e7bcbce9d56411483309246/lib/websocket.js#L1053

But because we removed the listeners earlier (and they were the only one present), we were not able to handle them.

We could perhaps move the this._cleanupConnection(); call to after the this.connection.close() call to avoid this error, can you patch the code and try if that works? It should in essence be the following change:

image

cc: @vladfrangu

@imranbarbhuiya
Copy link
Contributor

imranbarbhuiya commented May 24, 2022

ig it's related to #7581

@crycode-de
Copy link
Author

We could perhaps move the this._cleanupConnection(); call to after the this.connection.close() call to avoid this error, can you patch the code and try if that works? It should in essence be the following change:

I've tried this, but the error stays the same.

grafik

@kyranet
Copy link
Member

kyranet commented May 24, 2022

Can't confirm without debugging (please use one!), but I suppose it's because this line is called:

https://github.com/websockets/ws/blob/a690791df31cede48e7bcbce9d56411483309246/lib/websocket.js#L1050

That does... complicate some things. We could process.nextTick(() => this._cleanupConnection()); (still after this.connection.close, so it's queued after), but I'm unsure if that'll break something.

@legendhimself
Copy link
Contributor

legendhimself commented May 24, 2022

ig it's related to #7581

umm, I don't think so. Why? Because during close code 4009 it won't execute the else block which has _cleanupConnection method, Since the above if statement is true. I am saying this as I debugged this issue for almost over 2 months now.
I think cleaning up the during onClose event is better[which already we are] and should be removed from destroy method. Anyways my pr auto emits the onClose if the close frame(which is responsible for onClose event) wasn't received due to any issue so cleanup will happen.

@crycode-de
Copy link
Author

Changing to process.nextTick(() => this._cleanupConnection()); leads to an other error, since this.connection is null on the next tick:

Logs
[WS => Shard 0] [HeartbeatTimer] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.
    Status          : READY
    Sequence        : 1
    Connection State: OPEN
[WS => Shard 0] [DESTROY]
    Close Code    : 4009
    Reset         : true
    Emit DESTROYED: true
[WS => Shard 0] Clearing the heartbeat interval.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 9
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CLOSED
/home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:769
    this.connection.onopen = this.connection.onclose = this.connection.onerror = this.connection.onmessage = null;
                                                                                                           ^

TypeError: Cannot set properties of null (setting 'onmessage')
    at WebSocketShard._cleanupConnection (/home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:769:108)
    at /home/peter/tmp/node_modules/discord.js/src/client/websocket/WebSocketShard.js:731:37
    at processTicksAndRejections (node:internal/process/task_queues:78:11)

If I remove the call of this._cleanupConnection() it seams to work and tries reconnect every 5 seconds, but don't know if this might lead to other issues:

Logs
[WS => Shard 0] [HeartbeatTimer] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.
    Status          : READY
    Sequence        : 1
    Connection State: OPEN
[WS => Shard 0] [DESTROY]
    Close Code    : 4009
    Reset         : true
    Emit DESTROYED: true
[WS => Shard 0] Clearing the heartbeat interval.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 9
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CLOSED
[WS => Shard 0] Failed to connect to the gateway, requeueing...
[WS => Manager] Shard Queue Size: 1; continuing in 5 seconds...
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 9
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CLOSED
[WS => Shard 0] Failed to connect to the gateway, requeueing...
[WS => Manager] Shard Queue Size: 1; continuing in 5 seconds...
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 9
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CLOSED
[WS => Shard 0] Failed to connect to the gateway, requeueing...
[WS => Manager] Shard Queue Size: 1; continuing in 5 seconds...
[WS => Shard 0] [CONNECT]
    Gateway    : wss://gateway.discord.gg/
    Version    : 9
    Encoding   : json
    Compression: none
[WS => Shard 0] Setting a HELLO timeout for 20s.
[WS => Shard 0] [CLOSE]
    Event Code: 1006
    Clean     : false
    Reason    : 
[WS => Shard 0] Clearing the HELLO timeout.
[WS => Shard 0] WS State: CLOSED
[WS => Shard 0] Failed to connect to the gateway, requeueing...
[WS => Manager] Shard Queue Size: 1; continuing in 5 seconds...
[WS => Shard 0] [CONNECT]

@legendhimself
Copy link
Contributor

legendhimself commented May 24, 2022

@crycode-de
I tried to recreate this issue but I am failing to recreate the exact same thing. With djs v13.7.0 it reconnects perfectly fine after i plug/unplug. Also can you please try to replicate this issue using my pr #7581 ?

You can download it from here
npm => npm install github:legendhimslef/discord.js#v13
yarn => yarn add discord.js@github:legendhimslef/discord.js#v13

@crycode-de
Copy link
Author

@legendhimslef
Using your PR #7581 seams to work fine. The error then gets emitted as shardError and a reconnect is queued. 👍

@fredkilbourn
Copy link

I just had this same error today using discord.js 13.8.0:

Uncaught Exception:
Error: WebSocket was closed before the connection was established
    at WebSocket.close (/home/vbot/srv/vbot/node_modules/ws/lib/websocket.js:285:14)
    at WebSocketShard.destroy (/home/vbot/srv/vbot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:806:27)
    at WebSocketShard.onClose (/home/vbot/srv/vbot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:370:12)
    at WebSocket.onClose (/home/vbot/srv/vbot/node_modules/ws/lib/event-target.js:210:18)
    at WebSocket.emit (node:events:526:28)
    at WebSocket.emitClose (/home/vbot/srv/vbot/node_modules/ws/lib/websocket.js:258:10)
    at Receiver.receiverOnFinish (/home/vbot/srv/vbot/node_modules/ws/lib/websocket.js:1158:20)
    at Receiver.emit (node:events:526:28)
    at finish (node:internal/streams/writable:754:10)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

@legendhimself
Copy link
Contributor

legendhimself commented Jun 15, 2022

I just had this same error today using discord.js 13.8.0:

Uncaught Exception:
Error: WebSocket was closed before the connection was established
    at WebSocket.close (/home/vbot/srv/vbot/node_modules/ws/lib/websocket.js:285:14)
    at WebSocketShard.destroy (/home/vbot/srv/vbot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:806:27)
    at WebSocketShard.onClose (/home/vbot/srv/vbot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:370:12)
    at WebSocket.onClose (/home/vbot/srv/vbot/node_modules/ws/lib/event-target.js:210:18)
    at WebSocket.emit (node:events:526:28)
    at WebSocket.emitClose (/home/vbot/srv/vbot/node_modules/ws/lib/websocket.js:258:10)
    at Receiver.receiverOnFinish (/home/vbot/srv/vbot/node_modules/ws/lib/websocket.js:1158:20)
    at Receiver.emit (node:events:526:28)
    at finish (node:internal/streams/writable:754:10)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

This was already patched in 13.8.0
Updating that we now have the this pr to fix some stuff: #8082
We might have this 👆 in 13.8.1

@fredkilbourn
Copy link

Thanks!

@wdfeww
Copy link

wdfeww commented Jul 1, 2022

same on 13.8.1 :(

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

Error: WebSocket was closed before the connection was established
    at WebSocket.close (/root/fs-dc/node_modules/ws/lib/websocket.js:285:14)
    at WebSocketShard.destroy (/root/fs-dc/node_modules/discord.js/src/client/websocket/WebSocketShard.js:806:27)
    at WebSocketShard.onClose (/root/fs-dc/node_modules/discord.js/src/client/websocket/WebSocketShard.js:370:12)
    at WebSocket.onClose (/root/fs-dc/node_modules/ws/lib/event-target.js:210:18)
    at WebSocket.emit (node:events:527:28)
    at WebSocket.emitClose (/root/fs-dc/node_modules/ws/lib/websocket.js:258:10)
    at Receiver.receiverOnFinish (/root/fs-dc/node_modules/ws/lib/websocket.js:1158:20)
    at Receiver.emit (node:events:527:28)
    at finish (node:internal/streams/writable:754:10)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)
Emitted 'error' event on WebSocket instance at:
    at emitErrorAndClose (/root/fs-dc/node_modules/ws/lib/websocket.js:993:13)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

@legendhimself
Copy link
Contributor

same on 13.8.1 :(

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

Error: WebSocket was closed before the connection was established
    at WebSocket.close (/root/fs-dc/node_modules/ws/lib/websocket.js:285:14)
    at WebSocketShard.destroy (/root/fs-dc/node_modules/discord.js/src/client/websocket/WebSocketShard.js:806:27)
    at WebSocketShard.onClose (/root/fs-dc/node_modules/discord.js/src/client/websocket/WebSocketShard.js:370:12)
    at WebSocket.onClose (/root/fs-dc/node_modules/ws/lib/event-target.js:210:18)
    at WebSocket.emit (node:events:527:28)
    at WebSocket.emitClose (/root/fs-dc/node_modules/ws/lib/websocket.js:258:10)
    at Receiver.receiverOnFinish (/root/fs-dc/node_modules/ws/lib/websocket.js:1158:20)
    at Receiver.emit (node:events:527:28)
    at finish (node:internal/streams/writable:754:10)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)
Emitted 'error' event on WebSocket instance at:
    at emitErrorAndClose (/root/fs-dc/node_modules/ws/lib/websocket.js:993:13)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

steps to recreate?

@imranbarbhuiya
Copy link
Contributor

#8164 will fix it

@legendhimself
Copy link
Contributor

#8164 will fix it

wait whats the point of silencing errors. We already have issues with socket hangups.

@imranbarbhuiya
Copy link
Contributor

u can read #8150 description

@ASHISHKUMAR2411
Copy link

at Timeout.onConnectTimeout [as _onTimeout] (D:\path\smart_contracts\node_modules\undici\lib\core\connect.js:108:24)
at listOnTimeout (node:internal/timers:559:11)
at processTimers (node:internal/timers:500:7) {
code: 'UND_ERR_CONNECT_TIMEOUT'
}```
I am trying to deploy my smart contract on alchemy using rinkeby testnet `npx hardhat verify --network rinkeby address`

@pedroricardo
Copy link

"discord.js": "13.9.0",

node:events:504
+      throw er; // Unhandled 'error' event
      ^
BError: WebSocket was closed before the connection was established
L    at WebSocket.close (/home/node/node_modules/ws/lib/websocket.js:285:14)
q    at WebSocketShard.destroy (/home/node/node_modules/discord.js/src/client/websocket/WebSocketShard.js:719:27)
o    at WebSocketShard._send (/home/node/node_modules/discord.js/src/client/websocket/WebSocketShard.js:659:12)
v    at WebSocketShard.processQueue (/home/node/node_modules/discord.js/src/client/websocket/WebSocketShard.js:685:12)
n    at WebSocketShard.send (/home/node/node_modules/discord.js/src/client/websocket/WebSocketShard.js:647:10)
w    at WebSocketManager.broadcast (/home/node/node_modules/discord.js/src/client/websocket/WebSocketManager.js:312:53)
f    at ClientPresence.set (/home/node/node_modules/discord.js/src/structures/ClientPresence.js:25:22)
g    at ClientUser.setPresence (/home/node/node_modules/discord.js/src/structures/ClientUser.js:120:33)
g    at ClientUser.setActivity (/home/node/node_modules/discord.js/src/structures/ClientUser.js:167:17)
H    at Timeout._onTimeout (/home/node/src/events/client/ready.js:31:44)

@iCrawl
Copy link
Member

iCrawl commented Aug 9, 2022

@pedroricardo Do you have an error handler attached to your client?

client.on('error', console.error);

@pedroricardo
Copy link

@iCrawl I do not have

@SpaceEEC
Copy link
Member

SpaceEEC commented Aug 9, 2022

The stacktrace suggests that you are running 13.4.0 (or even older): Please make sure you are actually running 13.9.2 where this issue should no longer occur.

@iCrawl
Copy link
Member

iCrawl commented Aug 9, 2022

@pedroricardo Additionally to the thing above, please also have an error handler like I showed.

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

Successfully merging a pull request may close this issue.