dotnet/aspnetcore · error · Error

Invalid payload for StreamItem message.

Error message

Invalid payload for StreamItem message.

What it means

A StreamItem message (type 2) must carry an `item` payload; an undefined item means the stream produced nothing, which the protocol treats as malformed because every StreamItem represents one emitted value.

Source

Thrown at src/SignalR/clients/ts/signalr/src/JsonHubProtocol.ts:105

     * @returns {string} A string containing the serialized representation of the message.
     */
    public writeMessage(message: HubMessage): string {
        return TextMessageFormat.write(JSON.stringify(message));
    }

    private _isInvocationMessage(message: InvocationMessage): void {
        this._assertNotEmptyString(message.target, "Invalid payload for Invocation message.");

        if (message.invocationId !== undefined) {
            this._assertNotEmptyString(message.invocationId, "Invalid payload for Invocation message.");
        }
    }

    private _isStreamItemMessage(message: StreamItemMessage): void {
        this._assertNotEmptyString(message.invocationId, "Invalid payload for StreamItem message.");

        if (message.item === undefined) {
            throw new Error("Invalid payload for StreamItem message.");
        }
    }

    private _isCompletionMessage(message: CompletionMessage): void {
        if (message.result && message.error) {
            throw new Error("Invalid payload for Completion message.");
        }

        if (!message.result && message.error) {
            this._assertNotEmptyString(message.error, "Invalid payload for Completion message.");
        }

        this._assertNotEmptyString(message.invocationId, "Invalid payload for Completion message.");
    }

    private _isAckMessage(message: AckMessage): void {
        if (typeof message.sequenceId !== 'number') {
            throw new Error("Invalid SequenceId for Ack message.");

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Ensure the streaming hub method never yields null/undefined; emit a concrete value or a sentinel object instead.
  2. If using a custom JSON serializer, configure it to preserve keys even for null values.
  3. Log the raw message (logMessageContent:true) to confirm whether `item` is missing on the wire.
  4. Align server and client SignalR versions so serialization semantics match.

Example fix

// server (TS hub) before
async function* stream() { yield undefined; }

// after
async function* stream() { yield { value: null }; }
Defensive patterns

Strategy: validation

Validate before calling

// server side: ensure every yielded item is defined
async function* stream() {
  const v = await nextValue();
  if (v === undefined) return; // stop instead of yielding undefined
  yield v;
}

Type guard

function hasItem(m: any): boolean {
  return m?.type === 2 && m.item !== undefined;
}

Try / catch

stream.subscribe({
  next: (item) => { /* ... */ },
  error: (e) => { /* stream-level errors surface here */ },
});

Prevention

When it happens

Trigger: Server sends {"type":2,"invocationId":"x"} with the `item` field omitted or explicitly null-as-undefined. Happens when a streaming hub method yields null/undefined through a serializer that drops undefined keys.

Common situations: A server-side ChannelAsyncEnumerable yields null, a custom serializer strips undefined fields, or a JS server that does `yield undefined`.

Related errors


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