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

JS exceptions thrown while just idling (WebSocket is already in CLOSING or CLOSED state.) #3259

Open
getify opened this issue May 26, 2018 · 48 comments

Comments

@getify
Copy link

commented May 26, 2018

You want to:

  • report a bug
  • request a feature

Current behaviour

While leaving a socket connected, but doing no other activity in my program, I see intermittently (but fairly consistently) an exception thrown in browser console, from inside of the socket.io machinery (specifically in backo2/index.js line 83. That error is:

WebSocket is already in CLOSING or CLOSED state.

socket-io-errors

Steps to reproduce (if the current behaviour is a bug)

I have two tabs open with client sockets connected to the same server (localhost) via https. Both clients are sitting idle with nothing else happening in browser or server (except for whatever keep-alive pings socket.io is doing). Both of them are joined to a single channel (via join(..) on the server). Otherwise, nothing else special.

Here's how I create the server socket instance:

var httpsServer = https.createServer(..);
var io = require("socket.io")(httpsServer);
io.on("connection",onSocketConnection);

And in the client:

socket = io();
socket.on("connect",function(){
   console.log("socket connected");
});
socket.on("disconnect",function(){
   console.log("socket disconnected");
});

Expected behaviour

I expect disconnections and reconnections from time to time, but I don't expect spurious JS exceptions thrown by the library when I'm not doing anything else over the connections.

Setup

  • OS: Mac OSX
  • browser: Chrome 66, node 10.2.1
  • socket.io version: 2.1.1

Other information (e.g. stacktraces, related issues, suggestions how to fix)

Expanded stack trace:

index.js:83 WebSocket is already in CLOSING or CLOSED state.
(anonymous) @ index.js:83
e.encodePacket @ index.js:83
(anonymous) @ index.js:83
r.write @ index.js:83
r.send @ index.js:83
r.flush @ index.js:83
r.sendPacket @ index.js:83
r.ping @ index.js:83
(anonymous) @ index.js:83
setTimeout (async)
r.setPing @ index.js:83
r.onPacket @ index.js:83
(anonymous) @ index.js:83
r.emit @ index.js:83
r.onPacket @ index.js:83
r.onData @ index.js:83
ws.onmessage @ index.js:83
@antoniab123456

This comment has been minimized.

Copy link

commented Jun 8, 2018

Experiencing absolutely the same issue and the code is correct. This only happens in Chrome for me. Mozilla is clean. In chrome, this err is raining over and over and duplicating all the chats I have. I tried using this method
socket.on('disconnect', () =>{ socket.disconnect(); });
It doesn't disconnect the client from the server. Repo in case needed https://github.com/antoniab123456/Chat_app

@danghung-dev

This comment has been minimized.

Copy link

commented Jun 13, 2018

the same problem here
image

browser is just idling, then the errors come up.

I used Chrome and mac OS

@antoniab123456

This comment has been minimized.

Copy link

commented Jun 16, 2018

Yes guys, can someone address that? Perhaps we need another line of code to fix that?

@dtroydev

This comment has been minimized.

Copy link

commented Jun 19, 2018

I have the same problem with socket.io and Chrome
Mac OS 10.13.5
Chrome Version 67.0.3396.87 (Official Build) (64-bit)
Node: 10.3.0
Express: 4.16.3
socket.io: 2.1.1

In Firefox everything is fine.

Error details below:

index.js:83 WebSocket is already in CLOSING or CLOSED state.
(anonymous) | @ | index.js:83
  | e.encodePacket | @ | index.js:83
  | (anonymous) | @ | index.js:83
  | r.write | @ | index.js:83
  | r.send | @ | index.js:83
  | r.flush | @ | index.js:83
  | r.sendPacket | @ | index.js:83
  | r.ping | @ | index.js:83
  | (anonymous) | @ | index.js:83
  | setTimeout (async) |   |  
  | r.setPing | @ | index.js:83
  | r.onPacket | @ | index.js:83
  | (anonymous) | @ | index.js:83
  | r.emit | @ | index.js:83
  | r.onPacket | @ | index.js:83
  | r.onData | @ | index.js:83
  | ws.onmessage | @ | index.js:83

When I click on the index.js:83 it takes me to this module:

/**
 * Expose `Backoff`.
 */

module.exports = Backoff;

/**
 * Initialize backoff timer with `opts`.
 *
 * - `min` initial timeout in milliseconds [100]
 * - `max` max timeout [10000]
 * - `jitter` [0]
 * - `factor` [2]
 *
 * @param {Object} opts
 * @api public
 */

function Backoff(opts) {
  opts = opts || {};
  this.ms = opts.min || 100;
  this.max = opts.max || 10000;
  this.factor = opts.factor || 2;
  this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
  this.attempts = 0;
}

/**
 * Return the backoff duration.
 *
 * @return {Number}
 * @api public
 */

Backoff.prototype.duration = function(){
  var ms = this.ms * Math.pow(this.factor, this.attempts++);
  if (this.jitter) {
    var rand =  Math.random();
    var deviation = Math.floor(rand * this.jitter * ms);
    ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation;
  }
  return Math.min(ms, this.max) | 0;
};

/**
 * Reset the number of attempts.
 *
 * @api public
 */

Backoff.prototype.reset = function(){
  this.attempts = 0;
};

/**
 * Set the minimum duration
 *
 * @api public
 */

Backoff.prototype.setMin = function(min){
  this.ms = min;
};

/**
 * Set the maximum duration
 *
 * @api public
 */

Backoff.prototype.setMax = function(max){
  this.max = max;
};

/**
 * Set the jitter
 *
 * @api public
 */

Backoff.prototype.setJitter = function(jitter){
  this.jitter = jitter;
};




//////////////////
// WEBPACK FOOTER
// ./~/backo2/index.js
// module id = 41
// module chunks = 0

Line 83 is:

this.jitter = jitter;
@kino2007

This comment has been minimized.

Copy link

commented Jul 2, 2018

I sort of have the same problem, with backo2.js and in line 83. here is my error:
index.js:83 Uncaught TypeError: Failed to execute 'readAsArrayBuffer' on 'FileReader': parameter 1 is not of type 'Blob'.
at n (index.js:83)
at n (index.js:83)
at n (index.js:83)
at n (index.js:83)
at n (index.js:83)
at n (index.js:83)
at Object.e.removeBlobs (index.js:83)
at s (index.js:83)
at r.encode (index.js:83)
at r.packet (index.js:83)
and dont worry about the other stuff, they all are in line 83, which is this.jitter = jitter;
It is annoying me so much as there isnt really any solution in google.

@19smitgr

This comment has been minimized.

Copy link

commented Jul 2, 2018

Has anyone found a temporary solution? @antoniab123456 were you able to fix your chat app so that it doesn't duplicate your chats? It's doing the same thing to me.

Setup
OS: Mac OSX
Browser: Chrome 67.0.3396.99 (Official Build) (64-bit)
Node v10.5.0
Socket.io v2.1.1

@vkotu

This comment has been minimized.

Copy link

commented Jul 15, 2018

I am facing the exact problem @getify mentioned in chrome. Has any one found any work around for this?

@gavin310

This comment has been minimized.

Copy link

commented Jul 17, 2018

Same problem. Can someone please respond to this?

@amerej

This comment has been minimized.

Copy link

commented Jul 18, 2018

Same problem.

Setup
OS: Mac OSX
browser: Chrome 67.0.3396.99 (Official Build) (64-bit), Node 9.6.1
socket.io version: 2.1.1

@kino2007

This comment has been minimized.

Copy link

commented Jul 20, 2018

@19smitgr idk what you mean by 'dulplicate chats' which sounds off topic which could be solved by broadcasting instead if you mean 'duplicate message in same screen'.

@19smitgr

This comment has been minimized.

Copy link

commented Jul 20, 2018

@kino2007 I'm not making a chat application. I'm actually using websockets with a multiplayer game, and the websocket wasn't getting a disconnect message, so when the user disconnected and reconnected due to the random error that everyone is talking about, it would give the character a new socket ID, and the old sprite with the old socket ID wasn't deleted because it was just getting a "transport close" message instead of a "disconnect" message.

At this point, even if I get a "transport close" message, I just delete the user from my list of current users the same way as if I got a "disconnect" message.

@jld3103

This comment has been minimized.

Copy link

commented Jul 29, 2018

Same error here

After a quick search I found out that backo2 causes the error.

Then I used the dev version of socket.io and found out that the Socket.prototype.onevent throws the error.

@jld3103

This comment has been minimized.

Copy link

commented Jul 29, 2018

I fixed it for me:

Previously I used this:

socket.on('ping', alert);

But then I changed it to this:

socket.on('ping', msg => {
    alert(msg);
});

And it worked!

@IainM22

This comment has been minimized.

Copy link

commented Aug 22, 2018

I'm having the same problem. Any updates on this?

@Evgenyx82

This comment has been minimized.

Copy link

commented Aug 24, 2018

Same here.

socket.io & socket.io-client: "^2.1.1"
MacOS
Google Chrome is up to date
Version 68.0.3440.106 (Official Build) (64-bit)

@abhyuditjain

This comment has been minimized.

Copy link

commented Aug 30, 2018

I am having the same issue. Also, it's duplicating messages I send from server to client.

screen shot 2018-08-30 at 4 51 49 pm

MacOS: 10.13.6
Socket.io: "^2.1.1"
Chrome: 68.0.3440.106

@vkotu

This comment has been minimized.

Copy link

commented Aug 30, 2018

@abhyuditjain You can try reset all the listener's using socket.removeAllListeners(); to avoid multiple listener registrations which might cause the duplicating messages.

@Asher978

This comment has been minimized.

Copy link

commented Sep 4, 2018

This seems to be an ongoing issue for several people and there has not been any solution to this. Any updates from anyone?

@abhyuditjain

This comment has been minimized.

Copy link

commented Sep 4, 2018

@vkotu If I remove all the listeners, then the socket doesn't reconnect to server on disconnect. Any way to fix this?

@antoniab123456

This comment has been minimized.

Copy link

commented Sep 5, 2018

just use websocket- node, it is easy to use and works without any errors and plus you don't need an external library for that:
https://codeburst.io/why-you-don-t-need-socket-io-6848f1c871cd
https://medium.com/@martin.sikora/node-js-websocket-simple-chat-tutorial-2def3a841b61
https://www.npmjs.com/package/websocket

@antoniab123456

This comment has been minimized.

Copy link

commented Sep 5, 2018

@cozuya

This comment has been minimized.

Copy link

commented Sep 20, 2018

Downgrading to 2.0.3 "fixed" this issue for me.

@Asher978

This comment has been minimized.

Copy link

commented Sep 20, 2018

@cozuya going to test it. Will let you know if it worked!

@Asher978

This comment has been minimized.

Copy link

commented Sep 20, 2018

Downgrading to 2.0.3 "fixed" this issue for me.

seems to be doing the trick. Tested for 4 mins and no errors. Let see how long it holds!

@cozuya thanks for posting this!

@icastillejogomez

This comment has been minimized.

Copy link

commented Sep 23, 2018

Same error in 2.1.1

Downgrading to 2.0.3 "fixed" this issue for me.

2.0.3 works for me! Thanks @cozuya

@wannymiarelli

This comment has been minimized.

Copy link

commented Sep 27, 2018

2.1.1 still facing the same issues. Tried to incrase ping and timeout but nothing changed

@rriixx

This comment has been minimized.

Copy link

commented Sep 27, 2018

having the same issue in chrome with v2.1.1, while browser is idling for a long time (about 20-30 minutes)

@Asher978

This comment has been minimized.

Copy link

commented Sep 27, 2018

2.1.1 still facing the same issues. Tried to incrase ping and timeout but nothing changed

downgrade to v 2.0.3

@thomas-lee

This comment has been minimized.

Copy link

commented Oct 22, 2018

I have tried to use socket.io with 2.0.4, it looks normal.

I have found there is a change for the pingTimeout from 60000(v2.0.4) to 5000 (v2.1.1)

If I have changed pingTimeout to a larger number like 10000s, it seems working.

I guess it may relate to the browser idle where inactive tab will have some throttle.

@MuhammedAlmaz

This comment has been minimized.

Copy link

commented Oct 24, 2018

I had some problem .Did someone solved the issue?

@DavidNeiOs

This comment has been minimized.

Copy link

commented Oct 31, 2018

I had to downgrade too. It was not working for chrome and safari

@HorseBadorties

This comment has been minimized.

Copy link

commented Nov 28, 2018

Same problem here. Chrome under OSX.

I work around it not using socket.removeAllListeners(); but socket.off("whatever") for all my non-technical listeners besides "disconnect" and so forth. Works fine. The error messages in the browser console are annoying but not worth a downgrade for me.

I have to say it's disappointing to see this issue without any attention whatsoever. It's six month and counting.

@Asher978

This comment has been minimized.

Copy link

commented Nov 29, 2018

@gbwashleybrown

This comment has been minimized.

Copy link

commented Dec 9, 2018

Same issue.... surprised no fix has been made for this yet.

@MLG-ANolan

This comment has been minimized.

Copy link

commented Dec 13, 2018

I to have run into this issue. In my case the disconnect was due to ping timeout. However, no luck on why the client side stopped responding to pings.

io.on('connection', function(socket) {
  socket.on('disconnect', function(reason) {
  console.log(`Socket disconnected for: ${reason}`);
  }
});

https://socket.io/docs/server-api/#Event-%E2%80%98disconnect%E2%80%99 has a list of reason for disconnections.

More Debugging:
image
One observation is that the ping event on the client is +30s from the last. Each and every time i saw the disconnect, its was 30s+ which is the default heartbeat interval + ping timeout. +26s, +28s, and +29s did show up without a disconnect.
When comparing against Safari, Safari was more consistent on pinging every 25s and did not see any disconnects.

@omardoma

This comment has been minimized.

Copy link

commented Dec 18, 2018

There is a change for the default pingTimeout from 60000(v2.0.4) to 5000 (v2.1.0+) which is not enough for some browsers like Chrome.

The solution to this issue on v2.1.0+ including the latest v2.2.0 is to override the default pingTimeout on your server to a large value as follows:

const http = require('http');
const server = http.createServer();
const io = require('socket.io')(server, {
  pingTimeout: 60000,
});

OR

const io = require('socket.io')();
const http = require('http');
const server = http.createServer();
io.attach(server, {
  pingTimeout: 60000,
});
@LunarMist

This comment has been minimized.

Copy link

commented Jan 1, 2019

Why is 5000 not enough? I am seeing this issue on my local dev server, and the latency between the client and server is most certainly under that threshold. 5000ms seems like a reasonable timeout. Smells like there could be an issue with the ping-pong system itself, and it only manifested when it was lowered.

@crobinson42

This comment has been minimized.

Copy link

commented Mar 19, 2019

Thx for getting this thread started @getify (I'm on socket.io v2.2.0)

To anyone that is also experiencing this - ME TOO COMMENTS DON'T HELP :-) please vote up the issue with a thumb to show your support 👍

Thx @omardoma for discovering the pingTimeout and I agree with @LunarMist that the we should investigate the ping/pong event system.

I did some preliminary testing with Chrome, Firefox, & Safari (all on MacOS).

Chrome & Safari both appear to throttle ws activity with different behavior & constraints:

  • Chrome, after ~5min of inactivity when the tab is focused or immediately when the tab goes into the background. This is intentional by the chromium team (https://developers.google.com/web/updates/2017/03/background_tabs)
  • Safari, almost immediately when app focus is changed to another desktop app (MacOS) or when the tab goes into the background. Related to #2924
  • Firefox, *never has any issues mentioned in this thread

Solutions

I tested for several hours with all 3 of these browsers, changing the pingTimeout & pingInterval values. What I found to be solutions:

  1. Setting pingTimeout >= 30000ms
  • or -
  1. Setting pingInterval <= 10000ms

I believe the best solution to be changing pingTimeout = 30000. The default pingInterval is 25000ms and increasing the frequency of the clients pinging the server to every 10s can be too chatty for at scale projects.


Are @darrachequesne or any other repo members in favor of increasing the default pingTimeout to 30000 from the current default of 5000ms which was changed in v2.1 from 60000ms?

@donifer

This comment has been minimized.

Copy link

commented Mar 19, 2019

Reacting to your own comment also doesn't help.

The clients are the ones pinging the the server and not the other way around.

@darrachequesne

This comment has been minimized.

Copy link
Member

commented Mar 20, 2019

I think that's because the current version of socket.io relies on the setTimeout on the client side, which may not be as reliable as expected.

I think increasing the pingTimeout should temporarily fix the issue, but we'll use ping/pong from the server -> client (instead of the current client -> server) in v3.

@Ysunil016

This comment has been minimized.

Copy link

commented Apr 11, 2019

Just use the following code at the client end.

socket.on('ping', () => {
socket.emit(data);
});

@focux

This comment has been minimized.

Copy link

commented Apr 22, 2019

Thank you @crobinson42! Ping timeout solution worked great for me. I'm just having some concerns about that solution. If you lost internet connection in any moment, it will take up to 30 seconds for the disconnect event to be fired and for some apps, that's too much. e.g. a chat app that wants to disable text input when user is not connected.

In this case, increase the ping interval would do the work but as you said, the cost is high, is there any workaround for this?

@getify getify closed this Apr 23, 2019

@getify getify reopened this Apr 23, 2019

@FaizanZahid

This comment has been minimized.

Copy link

commented May 9, 2019

Please let us know once this is fixed, same issue for me, my versions r below:

"socket.io": "2.2.0",
"socket.io-adapter": "~1.1.1",
"socket.io-client": "2.2.0",
"socket.io-parser": "~3.2.0",
"socket.io-redis": "^5.2.0",

My Code:
server, {
path: '/socket.io',
serveClient: true,
// below are engine.IO options
pingInterval: 40000,
pingTimeout: 25000,
upgradeTimeout: 30000, // default value is 10000ms, try changing it to 20k or more
agent: false,
cookie: false,
rejectUnauthorized: false,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000
}

my client:

reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
reconnectionAttempts: Infinity,
//our site options
transports: ["polling", "websocket"],
secure: true,
rejectUnauthorized: false,
forceNew: true,
timeout: 60000

@Ysunil016

This comment has been minimized.

Copy link

commented May 9, 2019

@abhijitsdeshmukh

This comment has been minimized.

Copy link

commented May 14, 2019

Possibly a workaround on client side if anybody is interested till the issue is fixed. This will cause browser to not free up memory and may cause excessive memory usage.

If anybody has Chrome workaround, that would help

@cozuya

This comment has been minimized.

Copy link

commented May 15, 2019

You use Safari for localhost webdev? 🤔

@abhijitsdeshmukh

This comment has been minimized.

Copy link

commented May 15, 2019

You use Safari for localhost webdev? 🤔

Not really, but it is annoying with constant disconnects to test my app. This provides a temporary workaround till it is fixed in 3.0. This is not a solution. I posted if it will help somebody during dev.

@wumke

This comment has been minimized.

Copy link

commented Jul 1, 2019

I'm using very low pingInterval and pingTimeouts to get realtime offline status changes, setting it to 30 seconds would break my flow... does anybody know a way to solve this issue so I can use the long timeout 'fix' for backgrounded browser tabs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.