dotnet/aspnetcore · error · Error

Invalid message type.

Error message

Invalid message type.

What it means

Thrown in the write path (writeMessage switch default) when asked to serialize a HubMessage whose type is not one of Invocation, StreamInvocation, Completion, Ping, CancelInvocation, Close, Ack, or Sequence. It is a programmer-error guard: you constructed or passed a HubMessage with an unknown/invalid MessageType enum value.

Solutions

  1. Verify the message.type is a known MessageType enum value before calling write.
  2. Align @microsoft/signalr and @microsoft/signalr-protocol-msgpack to the same version so the enum mapping is consistent.
  3. If writing a new message kind, you are extending the protocol — branch on type explicitly rather than relying on the default arm.

Example fix

// before
protocol.write({ type: 99, ... }); // unknown enum → throws

// after — guard known types before write
if (!Object.values(MessageType).includes(msg.type)) {
  throw new TypeError(`Refusing to write unknown MessageType ${msg.type}`);
}
const bytes = protocol.write(msg);
Defensive patterns

Strategy: validation

Validate before calling

const SERIALIZABLE = new Set([MessageType.Invocation, MessageType.StreamInvocation, MessageType.Completion, MessageType.Ping, MessageType.CancelInvocation, MessageType.Close, MessageType.Ack, MessageType.Sequence]);
function isSerializableMessageType(t: unknown): boolean {
  return SERIALIZABLE.has(t as MessageType);
}
if (!isSerializableMessageType(msg.type)) throw new TypeError(`Unsupported MessageType ${msg.type}`);

Type guard

function isKnownMessageType(t: unknown): t is MessageType {
  return typeof t === 'number' && t >= 1 && t <= 7 || t === 8 || t === 9;
}

Try / catch

try { return protocol.write(msg); }
catch (e) {
  if (/Invalid message type/.test((e as Error).message)) {
    throw new TypeError(`Refusing to serialize message of type ${(msg as any).type}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling protocol.write(...) (directly or via HubConnection.send/invoke/stream) with a hand-built message whose type field is undefined, numeric garbage, or a future enum value the protocol version does not know how to serialize.

Common situations: Building custom HubMessage objects; mismatched @microsoft/signalr-protocol-msgpack version vs @microsoft/signalr (MessageType enum drift); a stale message object captured before an upgrade.

Related errors


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

Appendix: source

Thrown at src/SignalR/clients/ts/signalr-protocol-msgpack/src/MessagePackHubProtocol.ts:123

                return this._writeInvocation(message as InvocationMessage);
            case MessageType.StreamInvocation:
                return this._writeStreamInvocation(message as StreamInvocationMessage);
            case MessageType.StreamItem:
                return this._writeStreamItem(message as StreamItemMessage);
            case MessageType.Completion:
                return this._writeCompletion(message as CompletionMessage);
            case MessageType.Ping:
                return BinaryMessageFormat.write(SERIALIZED_PING_MESSAGE);
            case MessageType.CancelInvocation:
                return this._writeCancelInvocation(message as CancelInvocationMessage);
            case MessageType.Close:
                return this._writeClose();
            case MessageType.Ack:
                return this._writeAck(message as AckMessage);
            case MessageType.Sequence:
                return this._writeSequence(message as SequenceMessage);
            default:
                throw new Error("Invalid message type.");
        }
    }

    private _parseMessage(input: Uint8Array, logger: ILogger): HubMessage | null {
        if (input.length === 0) {
            throw new Error("Invalid payload.");
        }

        const properties = this._decoder.decode(input) as any;
        if (properties.length === 0 || !(properties instanceof Array)) {
            throw new Error("Invalid payload.");
        }

        const messageType = properties[0] as MessageType;

        switch (messageType) {
            case MessageType.Invocation:
                return this._createInvocationMessage(this._readHeaders(properties), properties);

View on GitHub (pinned to 3600ca084e)