dotnet/aspnetcore · error

Invalid message type.

Error message

Invalid message type.

What it means

Thrown by MessagePackHubProtocol.writeMessage() when the message's type field does not match any case in the MessageType enum switch (Invocation, StreamInvocation, StreamItem, Completion, Ping, CancelInvocation, Close, Ack, Sequence). It is the default branch, so any unrecognized or undefined type triggers it. This protects the encoder from emitting a malformed frame. It only fires on the outgoing (write) path, so it usually indicates a programming error in the caller building the HubMessage.

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 294cab2f9b)

Solutions

  1. Set message.type using the MessageType enum constant (e.g. MessageType.Invocation), not a literal number or string.
  2. Ensure both @microsoft/signalr and @microsoft/signalr-protocol-msgpack are the same version so the MessageType enum values line up.
  3. Before writing, assert the type: if (!isValidMessageType(message.type)) throw ... to catch the bug at the call site.
  4. When building Invocation/Completion messages use the documented factory shapes from the signalr package rather than hand-rolled objects.

Example fix

// before
protocol.writeMessage({ target: 'Send', arguments: [1] });

// after
import { MessageType } from '@microsoft/signalr';
protocol.writeMessage({
  type: MessageType.Invocation,
  target: 'Send',
  arguments: [1],
});
Defensive patterns

Strategy: type-guard

Validate before calling

import { MessageType } from '@microsoft/signalr';
const VALID_TYPES = new Set<number>(Object.values(MessageType).filter((v): v is number => typeof v === 'number'));
function assertWritable(message: { type?: number }) {
  if (message.type === undefined || !VALID_TYPES.has(message.type)) {
    throw new Error(`Refusing to write message with type ${message.type}`);
  }
}
assertWritable(msg);
protocol.writeMessage(msg as any);

Type guard

import { MessageType } from '@microsoft/signalr';
const VALID = new Set<number>(Object.values(MessageType).filter((v): v is number => typeof v === 'number'));
function isWritableMessageType(type: unknown): type is number {
  return typeof type === 'number' && VALID.has(type);
}

Try / catch

try {
  const buf = protocol.writeMessage(message);
} catch (e) {
  if (e.message === 'Invalid message type.') {
    throw new Error(`Cannot serialize message: type ${JSON.stringify((message as any).type)} is not a known MessageType`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling writeMessage({}) or writeMessage({ type: undefined }); passing a message object whose type is a string like "Invocation" instead of the numeric enum MessageType.Invocation; constructing a custom message type not in the enum.

Common situations: Calling writeMessage on a half-built message (forgot to set .type); deserializing JSON into a message object where type became a string; using an outdated @microsoft/signalr that lacks the Ack/Sequence enum values the current protocol version expects.

Related errors


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