Skip to content

SignalR Java SDK throwing UndeliverableException #31491

@aaronoe

Description

@aaronoe

Describe the bug

We are encountering a set of crashes from within the SignalR Java SDK. There are two separate issues but both are uncaught exceptions that currently crash our app. The two issues are:

  1. com.microsoft.signalr.HubConnection$ConnectionState.lambda$timeoutHandshakeResponse$0
    java.util.concurrent.TimeoutException: Timed out waiting for the server to respond to the handshake message.
  2. com.microsoft.signalr.HandshakeProtocol.parseHandshakeResponse
    HandshakeProtocol.java, line 21
    java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $

Note that the issue is not that the exception is being thrown in the first place, but that RxJava delivers it as an UndeliverableException and not through the subject as intended:

handshakeTimeout.schedule(() -> {
// If onError is called on a completed subject the global error handler is called
if (!(handshakeResponseSubject.hasComplete() || handshakeResponseSubject.hasThrowable()))
{
handshakeResponseSubject.onError(
new TimeoutException("Timed out waiting for the server to respond to the handshake message."));
}
}, timeout, unit);

I am wondering if there could be a race between the timeout and handleHandshake that could lead to the Subject being completed multiple times since there is no synchronization in place.

I'm also curious why the timeout is handled by creating a new executor instead of just using RxJava's timeout operator?

For the time being we are registering an RxJava error handler to log and swallow these exceptions but it would be good if this could be fixed and the errors are being propagated to the Completable that is returned by HubConnection.start()

To Reproduce

Wasn't able to reproduce this.

Exceptions (if any)

Stacktrace TimeoutException:

io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.util.concurrent.TimeoutException: Timed out waiting for the server to respond to the handshake message.
  at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
  at io.reactivex.subjects.CompletableSubject.onError(CompletableSubject.java:131)
  at com.microsoft.signalr.HubConnection$ConnectionState.lambda$timeoutHandshakeResponse$0(HubConnection.java:1428)
  at com.microsoft.signalr.HubConnection$ConnectionState.lambda$timeoutHandshakeResponse$0$HubConnection$ConnectionState(HubConnection.java)
  at com.microsoft.signalr.-$$Lambda$HubConnection$ConnectionState$_fs5XriBgCmY7mCMawuT2CL0Nx4.run(-.java)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:459)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:764)
  Caused by: java.util.concurrent.TimeoutException: Timed out waiting for the server to respond to the handshake message.
    at com.microsoft.signalr.HubConnection$ConnectionState.lambda$timeoutHandshakeResponse$0(HubConnection.java:1428)
    at com.microsoft.signalr.HubConnection$ConnectionState.lambda$timeoutHandshakeResponse$0$HubConnection$ConnectionState(HubConnection.java)
    at com.microsoft.signalr.-$$Lambda$HubConnection$ConnectionState$_fs5XriBgCmY7mCMawuT2CL0Nx4.run(-.java)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:459)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:764)

Stacktrace TimeoutException:

io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.lang.RuntimeException: An invalid handshake response was received from the server.
  at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
  at io.reactivex.subjects.CompletableSubject.onError(CompletableSubject.java:131)
  at com.microsoft.signalr.HubConnection$ConnectionState.handleHandshake(HubConnection.java:1407)
  at com.microsoft.signalr.HubConnection.ReceiveLoop(HubConnection.java:437)
  at com.microsoft.signalr.HubConnection.lambda$new$0(HubConnection.java:162)
  at com.microsoft.signalr.HubConnection.lambda$new$0$HubConnection(HubConnection.java)
  at com.microsoft.signalr.-$$Lambda$HubConnection$QTbpx7gje_2sI4dX1CsfAa9dG7g.invoke(-.java:2)
  at com.microsoft.signalr.WebSocketTransport.onReceive(WebSocketTransport.java:75)
  at com.microsoft.signalr.WebSocketTransport.lambda$start$0(WebSocketTransport.java:52)
  at com.microsoft.signalr.WebSocketTransport.lambda$start$0$WebSocketTransport(WebSocketTransport.java)
  at com.microsoft.signalr.-$$Lambda$WebSocketTransport$IuEB82SnLNJc1Av0IiMi3-Bx-v8.invoke(-.java)
  at com.microsoft.signalr.OkHttpWebSocketWrapper$SignalRWebSocketListener.onMessage(OkHttpWebSocketWrapper.java:100)
  at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:338)
  at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:247)
  at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:106)
  at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:293)
  at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.java:195)
  at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.java:519)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:919)
  Caused by: java.lang.RuntimeException: An invalid handshake response was received from the server.
    at com.microsoft.signalr.HubConnection$ConnectionState.handleHandshake(HubConnection.java:1406)
    at com.microsoft.signalr.HubConnection.ReceiveLoop(HubConnection.java:437)
    at com.microsoft.signalr.HubConnection.lambda$new$0(HubConnection.java:162)
    at com.microsoft.signalr.HubConnection.lambda$new$0$HubConnection(HubConnection.java)
    at com.microsoft.signalr.-$$Lambda$HubConnection$QTbpx7gje_2sI4dX1CsfAa9dG7g.invoke(-.java:2)
    at com.microsoft.signalr.WebSocketTransport.onReceive(WebSocketTransport.java:75)
    at com.microsoft.signalr.WebSocketTransport.lambda$start$0(WebSocketTransport.java:52)
    at com.microsoft.signalr.WebSocketTransport.lambda$start$0$WebSocketTransport(WebSocketTransport.java)
    at com.microsoft.signalr.-$$Lambda$WebSocketTransport$IuEB82SnLNJc1Av0IiMi3-Bx-v8.invoke(-.java)
    at com.microsoft.signalr.OkHttpWebSocketWrapper$SignalRWebSocketListener.onMessage(OkHttpWebSocketWrapper.java:100)
    at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:338)
    at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:247)
    at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:106)
    at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:293)
    at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.java:195)
    at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.java:519)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)
    Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
      at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
      at com.google.gson.Gson.fromJson(Gson.java:927)
      at com.google.gson.Gson.fromJson(Gson.java:892)
      at com.google.gson.Gson.fromJson(Gson.java:841)
      at com.google.gson.Gson.fromJson(Gson.java:813)
      at com.microsoft.signalr.HandshakeProtocol.parseHandshakeResponse(HandshakeProtocol.java:21)
      at com.microsoft.signalr.HubConnection$ConnectionState.handleHandshake(HubConnection.java:1404)
      at com.microsoft.signalr.HubConnection.ReceiveLoop(HubConnection.java:437)
      at com.microsoft.signalr.HubConnection.lambda$new$0(HubConnection.java:162)
      at com.microsoft.signalr.HubConnection.lambda$new$0$HubConnection(HubConnection.java)
      at com.microsoft.signalr.-$$Lambda$HubConnection$QTbpx7gje_2sI4dX1CsfAa9dG7g.invoke(-.java:2)
      at com.microsoft.signalr.WebSocketTransport.onReceive(WebSocketTransport.java:75)
      at com.microsoft.signalr.WebSocketTransport.lambda$start$0(WebSocketTransport.java:52)
      at com.microsoft.signalr.WebSocketTransport.lambda$start$0$WebSocketTransport(WebSocketTransport.java)
      at com.microsoft.signalr.-$$Lambda$WebSocketTransport$IuEB82SnLNJc1Av0IiMi3-Bx-v8.invoke(-.java)
      at com.microsoft.signalr.OkHttpWebSocketWrapper$SignalRWebSocketListener.onMessage(OkHttpWebSocketWrapper.java:100)
      at okhttp3.internal.ws.RealWebSocket.onReadMessage(RealWebSocket.java:338)
      at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:247)
      at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:106)
      at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:293)
      at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.java:195)
      at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.java:519)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
      at java.lang.Thread.run(Thread.java:919)

Further technical details

  • SignalR Java SDK 5.0.3

Metadata

Metadata

Assignees

Labels

area-signalrIncludes: SignalR clients and serversbugThis issue describes a behavior which is not expected - a bug.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions