microsoft/autogen · error · InvalidOperationException

Invalid streaming message type {reply.GetType().Name}

Error message

Invalid streaming message type {reply.GetType().Name}

What it means

InvalidOperationException thrown in OpenAIChatRequestMessageConnector.ProcessStreamingMessage when strictMode is true and a streamed reply item is not an IMessage<StreamingChatCompletionUpdate> envelope. The connector accumulates StreamingChatCompletionUpdate chunks to reassemble tool calls; strict mode rejects anything else rather than passing it through.

Source

Thrown at dotnet/src/AutoGen.OpenAI/Middleware/OpenAIChatRequestMessageConnector.cs:75

        var chunks = new List<StreamingChatCompletionUpdate>();

        // only streaming the text content
        await foreach (var reply in streamingReply)
        {
            if (reply is IMessage<StreamingChatCompletionUpdate> update)
            {
                if (update.Content.ContentUpdate.Count == 1 && update.Content.ContentUpdate[0].Kind == ChatMessageContentPartKind.Text)
                {
                    yield return new TextMessageUpdate(Role.Assistant, update.Content.ContentUpdate[0].Text, from: update.From);
                }

                chunks.Add(update.Content);
            }
            else
            {
                if (this.strictMode)
                {
                    throw new InvalidOperationException($"Invalid streaming message type {reply.GetType().Name}");
                }
                else
                {
                    yield return reply;
                }
            }
        }

        // process the tool call
        var streamingChatToolCallUpdates = chunks.Where(c => c.ToolCallUpdates.Count > 0)
                                                .SelectMany(c => c.ToolCallUpdates)
                                                .ToList();

        // collect all text parts
        var textParts = chunks.SelectMany(c => c.ContentUpdate)
            .Where(c => c.Kind == ChatMessageContentPartKind.Text)
            .Select(c => c.Text)
            .ToList();

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Use strictMode: false so non-envelope streaming items pass through untouched
  2. Order middlewares so this connector is the innermost (first to see raw SDK updates)
  3. Ensure only MessageEnvelope<StreamingChatCompletionUpdate> items reach it in strict pipelines

Example fix

// before
var connector = new OpenAIChatRequestMessageConnector(strictMode: true);
// stream contains TextMessageUpdate -> throws

// after
var connector = new OpenAIChatRequestMessageConnector(); // lenient passthrough
Defensive patterns

Strategy: type-guard

Validate before calling

// in a streaming pipeline, confirm items are raw SDK update envelopes before the strict connector sees them
bool ok = item is IMessage<StreamingChatCompletionUpdate>;

Type guard

static bool IsStreamingUpdateEnvelope(IMessage m) => m is IMessage<StreamingChatCompletionUpdate>;

Try / catch

catch (InvalidOperationException ex) when (ex.Message.StartsWith("Invalid streaming message type")) { /* reorder middlewares or disable strict mode */ }

Prevention

When it happens

Trigger: Streaming with OpenAIChatRequestMessageConnector(strictMode: true) where the pipeline yields TextMessageUpdate or other message types instead of raw StreamingChatCompletionUpdate envelopes — e.g. another middleware already transformed the stream.

Common situations: Stacking this connector after middleware that converts streaming chunks; piping one OpenAI agent's output into another strict agent's streaming pipeline; strict mode left on while composing middlewares.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/90997d24642effda. Report an issue: GitHub.