dotnet/aspnetcore · error · RuntimeException
Error reading NegotiateResponse
Error message
Error reading NegotiateResponse
What it means
Thrown when the Gson JsonReader hits an IOException while parsing the negotiate HTTP response (malformed JSON, an unexpected token type such as nextString() on a number, a truncated stream, or a network read failure mid-parse). The raw IOException is wrapped in a RuntimeException because the NegotiateResponse constructor does not declare checked exceptions.
Source
Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/NegotiateResponse.java:86
this.availableTransports.add(transport);
}
reader.endObject();
}
reader.endArray();
break;
case "connectionId":
this.connectionId = reader.nextString();
break;
default:
// Skip unknown property, allows new clients to still work with old protocols
reader.skipValue();
break;
}
} while (reader.hasNext());
reader.endObject();
reader.close();
} catch (IOException ex) {
throw new RuntimeException("Error reading NegotiateResponse", ex);
}
}
public NegotiateResponse(String url) {
this.finalUrl = url;
}
public String getConnectionId() {
return connectionId;
}
public Set<String> getAvailableTransports() {
return availableTransports;
}
public String getRedirectUrl() {
return redirectUrl;
}View on GitHub (pinned to 294cab2f9b)
Solutions
- Verify the negotiate URL returns a JSON object containing connectionId/availableTransports.
- Confirm you are targeting an ASP.NET Core SignalR hub, not legacy ASP.NET.
- Inspect the actual negotiate response body with curl/Postman and fix any proxy truncation.
- Ensure no auth redirect or error page intercepts the negotiate request.
Example fix
// diagnose before fixing client code:
// curl -i -X POST https://host/hub/negotiate -H 'Content-Length: 0'
// expect: {"connectionId":"...","availableTransports":[...]} Defensive patterns
Strategy: try-catch
Try / catch
// Java - start() propagates the wrapped RuntimeException
hubConnection.start().subscribe(
() -> { /* connected */ },
error -> {
if (error.getMessage() != null && error.getMessage().contains("NegotiateResponse")) {
// inspect server /negotiate endpoint, proxies, auth redirects
}
}); Prevention
- Validate the /negotiate endpoint returns JSON before wiring the client.
- Confirm the target is an ASP.NET Core (not legacy ASP.NET) SignalR hub.
- Make sure no auth redirect or HTML error page intercepts negotiate.
When it happens
Trigger: Server returns non-JSON or a partial body to the /negotiate POST; a field arrives as the wrong JSON type; connection drops during negotiate read; an auth redirect returns HTML instead of JSON.
Common situations: Connecting through a reverse proxy/gateway that strips or truncates the negotiate response; pointing at a non-SignalR endpoint; hitting a legacy ASP.NET (non-Core) server; load balancer returning an HTML error page (502/503); CORS/auth returning HTML.
Related errors
- Unexpected status code returned from negotiate: %d %s.
- Negotiate redirection limit exceeded.
- Error reading JSON.
- Negotiation can only be skipped when using the WebSocket tra
- HubConnection trying to negotiate when not in the CONNECTING
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/6c72b325a6269b99.
Report an issue: GitHub.