getting the reason why websockets closed with close code 1006
Solution 1:
Close Code 1006
is a special code that means the connection was closed abnormally (locally) by the browser implementation.
If your browser client reports close code 1006
, then you should be looking at the websocket.onerror(evt)
event for details.
However, Chrome will rarely report any close code 1006
reasons to the Javascript side. This is likely due to client security rules in the WebSocket spec to prevent abusing WebSocket. (such as using it to scan for open ports on a destination server, or for generating lots of connections for a denial-of-service attack).
Note that Chrome will often report a close code 1006
if there is an error during the HTTP Upgrade to Websocket (this is the step before a WebSocket is technically "connected"). For reasons such as bad authentication or authorization, or bad protocol use (such as requesting a subprotocol, but the server itself doesn't support that same subprotocol), or even an attempt at talking to a server location that isn't a WebSocket (such as attempting to connect to ws://images.google.com/
)
Fundamentally, if you see a close code 1006
, you have a very low level error with WebSocket itself (similar to "Unable to Open File" or "Socket Error"), not really meant for the user, as it points to a low level issue with your code and implementation. Fix your low level issues, and then when you are connected, you can then include more reasonable error codes. You can accomplish this in terms of scope or severity in your project. Example: info and warning level are part of your project's specific protocol, and don't cause the connection to terminate. With severe or fatal messages reporting also using your project's protocol to convey as much detail as you want, and then closing the connection using the limited abilities of the WebSocket close flow.
Be aware that WebSocket close codes are very strictly defined, and the close reason phrase/message cannot exceed 123 characters in length (this is an intentional WebSocket limitation).
But not all is lost, if you are just wanting this information for debugging reasons, the detail of the closure, and its underlying reason is often reported with a fair amount of detail in Chrome's Javascript console.
Solution 2:
In my and possibly @BIOHAZARD case it was nginx proxy timeout
. In default it's 60
sec without activity in socket
I changed it to 24h in nginx
and it resolved problem
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
Solution 3:
It looks like this is the case when Chrome is not compliant with WebSocket standard. When the server initiates close and sends close frame to a client, Chrome considers this to be an error and reports it to JS side with code 1006 and no reason message. In my tests, Chrome never responds to server-initiated close frames (close code 1000) suggesting that code 1006 probably means that Chrome is reporting its own internal error.
P.S. Firefox v57.00 handles this case properly and successfully delivers server's reason message to JS side.
Solution 4:
Thought this might be handy for others. Knowing regex is useful, kids. Stay in school.
Edit: Turned it into a handy dandy function!
let specificStatusCodeMappings = {
'1000': 'Normal Closure',
'1001': 'Going Away',
'1002': 'Protocol Error',
'1003': 'Unsupported Data',
'1004': '(For future)',
'1005': 'No Status Received',
'1006': 'Abnormal Closure',
'1007': 'Invalid frame payload data',
'1008': 'Policy Violation',
'1009': 'Message too big',
'1010': 'Missing Extension',
'1011': 'Internal Error',
'1012': 'Service Restart',
'1013': 'Try Again Later',
'1014': 'Bad Gateway',
'1015': 'TLS Handshake'
};
function getStatusCodeString(code) {
if (code >= 0 && code <= 999) {
return '(Unused)';
} else if (code >= 1016) {
if (code <= 1999) {
return '(For WebSocket standard)';
} else if (code <= 2999) {
return '(For WebSocket extensions)';
} else if (code <= 3999) {
return '(For libraries and frameworks)';
} else if (code <= 4999) {
return '(For applications)';
}
}
if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
return specificStatusCodeMappings[code];
}
return '(Unknown)';
}
Usage:
getStatusCodeString(1006); //'Abnormal Closure'
{
'0-999': '(Unused)',
'1016-1999': '(For WebSocket standard)',
'2000-2999': '(For WebSocket extensions)',
'3000-3999': '(For libraries and frameworks)',
'4000-4999': '(For applications)'
}
{
'1000': 'Normal Closure',
'1001': 'Going Away',
'1002': 'Protocol Error',
'1003': 'Unsupported Data',
'1004': '(For future)',
'1005': 'No Status Received',
'1006': 'Abnormal Closure',
'1007': 'Invalid frame payload data',
'1008': 'Policy Violation',
'1009': 'Message too big',
'1010': 'Missing Extension',
'1011': 'Internal Error',
'1012': 'Service Restart',
'1013': 'Try Again Later',
'1014': 'Bad Gateway',
'1015': 'TLS Handshake'
}
Source (with minor edits for terseness): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes
Solution 5:
I've got the error while using Chrome as client and golang gorilla websocket as server under nginx proxy
And sending just some "ping" message from server to client every x second resolved problem
Update: Oh boy I implemented dozens of websocket based apps after this answer and PINGING FROM CLIENT every 5 seconds is the correct way to keep connection with server alive (I do not know what was in my mind when I was recommending to ping from server)