dotnet/aspnetcore · error · RuntimeException

Invalid invocation result kind.

Error message

Invalid invocation result kind.

What it means

createCompletionMessage reads the integer result-kind field of an incoming CompletionMessage and switches on it; the protocol defines only ERROR_RESULT (1), VOID_RESULT (2), and NON_VOID_RESULT (3). Any other value means the message is malformed or produced by an incompatible peer, so the client refuses to interpret it.

Solutions

  1. Align the SignalR client and server to the same protocol version.
  2. If you control the sender, ensure resultKind is strictly 1, 2, or 3.
  3. Treat the occurrence as a connection-fatal protocol violation: tear down and reconnect to a compatible endpoint.

Example fix

// before - server emits an out-of-range result kind
// after - server uses the documented constants
packer.packInt(/*ERROR_RESULT*/1); // or 2 VOID_RESULT, 3 NON_VOID_RESULT
Defensive patterns

Strategy: validation

Validate before calling

// If you control the sender, assert resultKind is one of the defined constants before sending
int[] VALID = {/*ERROR_RESULT*/1, /*VOID_RESULT*/2, /*NON_VOID_RESULT*/3};
if (!IntStream.of(VALID).anyMatch(k -> k == resultKind)) {
    throw new IllegalArgumentException("Bad result kind: " + resultKind);
}

Type guard

static boolean isValidResultKind(int k) {
    return k == 1 || k == 2 || k == 3;
}

Try / catch

try {
    protocol.parseMessages(buffer, binder);
} catch (RuntimeException ex) {
    if ("Invalid invocation result kind.".equals(ex.getMessage())) {
        // protocol violation - reconnect to a compatible server
        connection.stop();
    }
    throw ex;
}

Prevention

When it happens

Trigger: The server sends a CompletionMessage whose resultKind is not 1, 2, or 3 (see MessagePackHubProtocol.java:45-47, 249-261). This is a wire/protocol violation, typically from a version mismatch between client and server MessagePack protocol implementations.

Common situations: Upgrading one side of the connection to a newer SignalR protocol that changed the result-kind encoding, corrupted bytes deserializing to an unexpected int, or a non-Microsoft server emitting non-standard completion frames.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/93492921ab3fe9b6. Report an issue: GitHub.

Appendix: source

Thrown at src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/MessagePackHubProtocol.java:260

        Map<String, String> headers = readHeaders(unpacker);
        String invocationId = unpacker.unpackString();
        int resultKind = unpacker.unpackInt();

        String error = null;
        Object result = null;

        switch (resultKind) {
            case ERROR_RESULT:
                error = unpacker.unpackString();
                break;
            case VOID_RESULT:
                break;
            case NON_VOID_RESULT:
                Type itemType = binder.getReturnType(invocationId);
                result = readValue(unpacker, itemType, payload, true);
                break;
            default:
                throw new RuntimeException("Invalid invocation result kind.");
        }

        return new CompletionMessage(headers, invocationId, result, error);
    }

    private HubMessage createStreamInvocationMessage(MessageUnpacker unpacker, InvocationBinder binder, int itemCount, ByteBuffer payload) throws IOException {
        Map<String, String> headers = readHeaders(unpacker);
        String invocationId = unpacker.unpackString();
        String target = unpacker.unpackString();

        Object[] arguments = null;
        try {
            List<Type> types = binder.getParameterTypes(target);
            arguments = bindArguments(unpacker, types, payload);
        } catch (Exception ex) {
            return new InvocationBindingFailureMessage(invocationId, target, ex);
        }

View on GitHub (pinned to 3600ca084e)