react-native: WebSocket module for Android crashes app when it fails to connect
When creating a new WebSocket connection, if the var ws = new WebSocket('....');
call fails to connect to the server, it will crash the app by throwing an error with message Cannot close WebSocket. Unknown WebSocket id 0
This is because the websocketFailed
event fires, which calls this._closeWebSocket(id);
inside WebSocket.js
. Since the connection was never open to begin with, calling WebSocket client = mWebSocketConnections.get(id);
inside WebSocketModule.java
will return null, hence triggering the exception throw new RuntimeException("Cannot close WebSocket. Unknown WebSocket id " + id);
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 50 (13 by maintainers)
Commits related to this issue
- Check that WS connection is open before closing it on 'websocketFailed'. Fixes #3346 — committed to yzarubin/react-native by yzarubin 9 years ago
- Check that WS connection is open before closing it on failed. Fixes #3346 Summary: Check that the WS state is set to OPEN before trying to close it when the ```websocketFailed``` event fires. Otherwi... — committed to expo/react-native by yzarubin 9 years ago
- Check that WS connection is open before closing it on failed. Fixes #3346 Summary: Check that the WS state is set to OPEN before trying to close it when the ```websocketFailed``` event fires. Otherwi... — committed to skillz/react-native by yzarubin 9 years ago
- Check that WS connection is open before closing it on failed. Fixes #3346 Summary: Check that the WS state is set to OPEN before trying to close it when the ```websocketFailed``` event fires. Otherwi... — committed to Crash--/react-native by yzarubin 9 years ago
- Use ConcurrentHashMap for handling concurrent Android websockets, and… Summary: … prevent unknown websocket IDs from crashing on Android (show warning on development builds instead) This PR addresse... — committed to facebook/react-native by sunweiyang 6 years ago
- Use ConcurrentHashMap for handling concurrent Android websockets, and… Summary: … prevent unknown websocket IDs from crashing on Android (show warning on development builds instead) This PR addresse... — committed to Plo4ox/react-native by sunweiyang 6 years ago
my problem : in javascript, the socket instance is connected and readyState is OPEN, but when i send a message, android app crash my solution is copy WebSocketModule.java as a CustomModule
@tanthanh289 can you send a pull request please? it takes very few minutes to send a PR with your changes if you have already fixed it and helps everyone.
Reopening since this is somewhat core and results in crashes.
@satya164, I’ve created PR #17884 to address this issue. Would like to greatly credit @tanthanh289 for inspiring this fix.
I’m a Javascript developer, no Java developer. The fact that I understand Java doesn’t mean I’m capable of analyzing the situation and provide a propper solution. I just wanted to point out, that currently there shouldn’t be a single RN app using RN’s websockets in the store, as they just break the app.
I have found one of problems is due to
HashMap
used formWebSocketConnections
in WebSocketModule.java.HashMap is not thread-safe, and can lose socket clients if concurrent sockets are opened at the same time.
If you can build RN from android source, just try this:
We are also experiencing this crash. It happens quite a lot , about 2%-3% of the sessions, to thousands of users. It seems like this is an ongoing issue, maybe it should be re-open?
We have hit this as well in our app that is currently in beta, but it is our second most hit crash already. We use websockets in a couple places, and we do the correct hardening in those locations in the javascript. It seems like a bug that the native layer would throw such an exception
The native layer still crashes with no way to prevent it from js. this happens for me when I enable airplane mode after making a websocket connection. I send a keepalive message every few seconds and when it fails because there is no connection I get this error. RN ~0.42.3
I tried a
try / catch
around the ws.send and also aif this.ws
but they both don’t prevent this error so I’m kind of stuck. How do I check if I can send a message if the ws object does not give me this information?edit: It seems possible to prevent this if I check for an internet connection before sending. But it should just raise a js error like a normal http request
+1
Please stop commenting with
+1
. It sends a notification to everyone in the thread and doesn’t achieve anything to resolve the issue.Many people have commented here with the fix, (especially @tanthanh289) and it’ll be useful if someone sends a pull request with that change to fix it. If this issue affects you, please send a pull request and mention me, and I’ll try to get it merged.
Really strange that you copy the code to fix it, but don’t wanna send a pull request.
This really needs to be adressed. Apps using the react native websockets in this state just can’t be published, because they are simply broken. You always can check the ready state before sending, but it seems that this isn’t really reliable. Then when you socket.send() you get the crash.
Or just send a PR?
My comment already states how to prevent the crash:
This should still error in the js and not in the java. Java errors are impossible to deal with from js. So I don’t get why this issue was closed. @ide
It’s still happening
@danieldelouya Copy the source java code as your custom socket module and fix the bug, copy the source javascript code as your custom socket component, it required your customer socket module, if the platform === ios return default socket, else return your custom socket, then where you need socket, require your custom socket
************* Crash Log Head **************** Device Manufacturer: Freescale Device Model : INBOX310 Android Version : 4.2.2 Android SDK : 17 App VersionName : 0.8.7 App VersionCode : 2 ************* Crash Log Head ****************
java.lang.RuntimeException: Cannot send a message. Unknown WebSocket id 0 at com.facebook.react.modules.websocket.WebSocketModule.send(WebSocketModule.java:199) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:363) at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:162) at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31) at android.os.Looper.loop(Looper.java:137) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:194) at java.lang.Thread.run(Thread.java:856)
This issue might be related to #8949
Two things we should do: fix the bug and make the native layer uncrashable.