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
- Set message.type using the MessageType enum constant (e.g. MessageType.Invocation), not a literal number or string.
- Ensure both @microsoft/signalr and @microsoft/signalr-protocol-msgpack are the same version so the MessageType enum values line up.
- Before writing, assert the type: if (!isValidMessageType(message.type)) throw ... to catch the bug at the call site.
- 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
- Always set message.type from the MessageType enum, never a literal string.
- Keep @microsoft/signalr and the msgpack protocol package on identical versions.
- When building messages programmatically, centralize construction in a factory that enforces the type field.
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
- Invalid input for MessagePack hub protocol. Expected an Arra
- Invalid headers.
- Unknown ${name} value: ${val}.
- descriptor must be defined when using a descriptor.
- sequence must be defined when using a descriptor.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/cdfed5c6fd69dd6b.
Report an issue: GitHub.