dotnet/aspnetcore · error · RuntimeException
Error reading JSON.
Error message
Error reading JSON.
What it means
GsonHubProtocol streams through the JSON with a JsonReader; any IOException (truncated token, unexpected end, malformed value) thrown during the parse loop is caught and rethrown as a RuntimeException with this message. It signals genuinely malformed JSON in a framed record.
Source
Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/GsonHubProtocol.java:220
case STREAM_INVOCATION:
case CANCEL_INVOCATION:
throw new UnsupportedOperationException(String.format("The message type %s is not supported yet.", messageType));
case PING:
hubMessages.add(PingMessage.getInstance());
break;
case CLOSE:
if (error != null) {
hubMessages.add(new CloseMessage(error));
} else {
hubMessages.add(new CloseMessage());
}
break;
default:
break;
}
}
} catch (IOException ex) {
throw new RuntimeException("Error reading JSON.", ex);
}
return hubMessages;
}
@Override
public ByteBuffer writeMessage(HubMessage hubMessage) {
return ByteBuffer.wrap((gson.toJson(hubMessage) + RECORD_SEPARATOR).getBytes(StandardCharsets.UTF_8));
}
private ArrayList<Object> bindArguments(JsonArray argumentsToken, List<Type> paramTypes) {
if (argumentsToken.size() != paramTypes.size()) {
throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argumentsToken.size(), paramTypes.size()));
}
ArrayList<Object> arguments = null;
if (paramTypes.size() >= 1) {
arguments = new ArrayList<>();View on GitHub (pinned to 294cab2f9b)
Solutions
- Capture the raw record bytes (enable message-content logging) and validate them with an external JSON parser.
- Confirm the transport delivers UTF-8 without re-encoding by intermediaries.
- Upgrade the server SignalR/serializer to rule out serialization bugs.
- If intermittent, suspect packet corruption or a proxy mangling the body.
Example fix
// diagnostics: log the offending record before parsing
for (String rec : payloadStr.split(RECORD_SEPARATOR)) {
try { new JsonParser().parse(rec); }
catch (Exception ex) { System.err.println("Bad record: " + rec); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate each framed record with a lenient parser before handing to the protocol
for (String rec : payload.split("\u001e")) {
try { JsonParser.parseString(rec); }
catch (Exception ex) { /* log offending record */ }
} Try / catch
try {
protocol.parseMessages(buffer, binder);
} catch (RuntimeException e) {
if ("Error reading JSON.".equals(e.getMessage()) && e.getCause() != null) {
// e.getCause() is the original IOException with parse location
}
} Prevention
- Validate transport delivers clean UTF-8 with no intermediary re-encoding.
- Log raw record bytes when debugging JSON parse failures.
- Upgrade server serializer to rule out serialization-side bugs.
When it happens
Trigger: A record that passed the record-separator framing check but contains invalid JSON: premature end of object, bad token, mismatched braces, or a number where a string is expected by the reader.
Common situations: Network corruption that leaves framing intact but breaks JSON, a buggy server serializer, a partial record that happens to end in 0x1e, or charset/encoding issues (non-UTF8 bytes).
Related errors
- Expected either 'error' or 'result' to be provided, but not
- Message is incomplete.
- The message type %s is not supported yet.
- Invocation provides %d argument(s) but target expects %d.
- The message type %s is not supported yet.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/be0185afdba64d12.
Report an issue: GitHub.