{"record":{"id":"66c6120675ffcf1f","repo":"dotnet/aspnetcore","slug":"there-were-no-compatible-transports-on-the-server","errorCode":null,"errorMessage":"There were no compatible transports on the server.","messagePattern":"There were no compatible transports on the server\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java","lineNumber":385,"sourceCode":"    private Single<NegotiateResponse> startNegotiate(String url, int negotiateAttempts, Map<String, String> localHeaders) {\n        if (this.state.getHubConnectionState() != HubConnectionState.CONNECTING) {\n            throw new RuntimeException(\"HubConnection trying to negotiate when not in the CONNECTING state.\");\n        }\n\n        return handleNegotiate(url, localHeaders).flatMap(response -> {\n            if (response.getRedirectUrl() != null && negotiateAttempts >= MAX_NEGOTIATE_ATTEMPTS) {\n                throw new RuntimeException(\"Negotiate redirection limit exceeded.\");\n            }\n\n            if (response.getRedirectUrl() == null) {\n                Set<String> transports = response.getAvailableTransports();\n                if (this.transportEnum == TransportEnum.ALL) {\n                    if (transports.contains(\"WebSockets\")) {\n                        response.setChosenTransport(TransportEnum.WEBSOCKETS);\n                    } else if (transports.contains(\"LongPolling\")) {\n                        response.setChosenTransport(TransportEnum.LONG_POLLING);\n                    } else {\n                        throw new RuntimeException(\"There were no compatible transports on the server.\");\n                    }\n                } else if (this.transportEnum == TransportEnum.WEBSOCKETS && !transports.contains(\"WebSockets\") ||\n                        (this.transportEnum == TransportEnum.LONG_POLLING && !transports.contains(\"LongPolling\"))) {\n                    throw new RuntimeException(\"There were no compatible transports on the server.\");\n                } else {\n                    response.setChosenTransport(this.transportEnum);\n                }\n\n                String connectionToken = \"\";\n                if (response.getVersion() > 0) {\n                    this.state.getConnectionState().connectionId = response.getConnectionId();\n                    connectionToken = response.getConnectionToken();\n                } else {\n                    connectionToken = response.getConnectionId();\n                    this.state.getConnectionState().connectionId = connectionToken;\n                }\n\n                String finalUrl = Utils.appendQueryString(url, \"id=\" + connectionToken);","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java#L367-L403","documentation":"Thrown during the SignalR negotiate handshake when the client is configured with TransportEnum.ALL but the server's negotiate response lists neither 'WebSockets' nor 'LongPolling' in its available transports. The client iterates the server-advertised transport set and falls through every supported option, so there is no transport it can use to establish the connection.","triggerScenarios":"Calling HubConnection.start() (which triggers negotiate) when the configured transport is TransportEnum.ALL and the server's /negotiate response 'availableTransports' array contains no entry matching 'WebSockets' or 'LongPolling' (e.g. server only advertises ServerSentEvents, which the Java client does not implement).","commonSituations":"Server-side Azure SignalR Service or ASP.NET Core hub configured to only allow SSE or a custom transport; version mismatch where a newer server advertises transports the older Java client cannot map; reverse proxy stripping the negotiate response; the hub endpoint requires Azure SignalR but the negotiate endpoint returned a minimal payload.","solutions":["Inspect the raw negotiate JSON response (enable TRACE logging or hit the /negotiate URL with curl) and confirm which strings appear in availableTransports.","On the server, ensure WebSockets (and/or LongPolling) is enabled in Configure<HubEndpointOptions> / AddSignalR(o => o.EnableDetailedErrors = true) and that IIS/Kestrel allows WebSockets.","Upgrade the signalr Java client to a version matching the server's protocol version so the advertised transport names line up.","If the server genuinely only offers an unsupported transport, switch to the JavaScript or .NET client which support SSE, or run a WebSocket-capable host."],"exampleFix":"// before\nHubConnectionBuilder.create(\"https://hub.example\")\n    .build(); // TransportEnum.ALL by default\n\n// after - confirm server offers WebSockets, then pin it\nHubConnectionBuilder.create(\"https://hub.example\")\n    .withTransport(TransportEnum.WEBSOCKETS)\n    .build();","handlingStrategy":"validation","validationCode":"// Before start(), probe the negotiate endpoint and confirm a usable transport.\n// (pseudo - use your HTTP client)\nResponse r = http.post(url + \"/negotiate\", headers);\nNegotiateJson body = parse(r);\nif (!body.availableTransports.contains(\"WebSockets\")\n    && !body.availableTransports.contains(\"LongPolling\")) {\n  throw new IllegalStateException(\n    \"Server offers no Java-compatible transport: \" + body.availableTransports);\n}","typeGuard":null,"tryCatchPattern":"// Wrap start() and surface the transport failure clearly.\nhub.start()\n  .subscribe(\n    () -> { /* connected */ },\n    err -> {\n      if (err.getMessage().contains(\"no compatible transports\")) {\n        // log availableTransports, alert ops to enable WebSockets/LongPolling\n      }\n    });","preventionTips":["Run a /negotiate smoke test in CI against the staging hub to assert availableTransports.","Pin the server transport configuration in code review so nobody disables WebSockets silently.","Document the required transport set next to the HubConnectionBuilder call."],"tags":["signalr","java","negotiate","transport","websocket","network"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}