{"record":{"id":"6093761043e1f8ec","repo":"microsoft/autogen","slug":"the-response-should-contain-either-text-or-tool-ca","errorCode":null,"errorMessage":"The response should contain either text or tool calls.","messagePattern":"The response should contain either text or tool calls\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs","lineNumber":108,"sourceCode":"                    var functionCallParts = bucket.Where(m => m.Candidates.Count == 1 && m.Candidates[0].Content.Parts.Count == 1 && m.Candidates[0].Content.Parts[0].DataCase == Part.DataOneofCase.FunctionCall)\n                        .Select(m => m.Candidates[0].Content.Parts[0]).ToList();\n\n                    var toolCalls = new List<ToolCall>();\n                    foreach (var part in functionCallParts)\n                    {\n                        var fc = part.FunctionCall;\n                        var toolCall = new ToolCall(fc.Name, fc.Args.ToString());\n\n                        toolCalls.Add(toolCall);\n                    }\n\n                    var toolCallMessage = new ToolCallMessage(toolCalls, agent.Name);\n\n                    yield return toolCallMessage;\n                }\n                else\n                {\n                    throw new InvalidOperationException(\"The response should contain either text or tool calls.\");\n                }\n            }\n        }\n    }\n\n    public async Task<IMessage> InvokeAsync(MiddlewareContext context, IAgent agent, CancellationToken cancellationToken = default)\n    {\n        var messages = ProcessMessage(context.Messages, agent);\n        var reply = await agent.GenerateReplyAsync(messages, context.Options, cancellationToken);\n\n        return reply switch\n        {\n            Core.IMessage<GenerateContentResponse> m => PostProcessMessage(m.Content, agent),\n            _ when strictMode => throw new InvalidOperationException($\"Unsupported message type: {reply.GetType()}\"),\n            _ => reply,\n        };\n    }\n","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs#L90-L126","documentation":"Thrown by GeminiMessageConnector while aggregating a streaming Gemini response: the bucket of GenerateContentResponse chunks contained neither pure-text parts nor any function-call parts. The connector can only fold streams into TextMessage or ToolCallMessage, so any other part kind (or an inconsistent mix) makes it throw InvalidOperationException.","triggerScenarios":"A Gemini stream where chunks carry parts whose DataCase is neither Text nor FunctionCall — e.g. inlineData/image parts, embedded metadata, or a stream mixing a text chunk with a function-call chunk such that neither the All(text) nor Any(functionCall) predicate holds.","commonSituations":"Multimodal replies (images/binary parts) from Gemini models, function-calling streams that also emit a text preamble chunk, or API version changes introducing new part kinds the connector does not recognize.","solutions":["Restrict the request so replies contain only text or function calls (don't request multimodal output with this connector)","Upgrade AutoGen.Gemini — newer connectors handle mixed/multimodal streams","Catch InvalidOperationException around streaming and fall back to non-streaming GenerateContentAsync for that turn"],"exampleFix":"// before: request asks Gemini for image output -> stream has inlineData parts -> throw\n// after: text-only generation config\nrequest.GenerationConfig = new GenerationConfig { ResponseModalities = { Modality.Text } };","handlingStrategy":"fallback","validationCode":"// Before requesting, constrain output modality to text\nrequest.GenerationConfig ??= new GenerationConfig();\nrequest.GenerationConfig.ResponseMimeTypes.Clear();\nrequest.GenerationConfig.ResponseModalities.Clear();\nrequest.GenerationConfig.ResponseModalities.Add(Modality.Text);","typeGuard":"static bool StreamIsFoldable(IEnumerable<GenerateContentResponse> chunks) =>\n    chunks.All(c => c.Candidates.Count == 1 &&\n                    c.Candidates[0].Content.Parts.All(p => p.DataCase is Part.DataOneofCase.Text or Part.DataOneofCase.FunctionCall));","tryCatchPattern":"try { await foreach (var m in geminiAgent.GenerateStreamingReplyAsync(msgs, ct)) { } }\ncatch (InvalidOperationException e) when (e.Message == \"The response should contain either text or tool calls.\")\n{ /* fall back to non-streaming GenerateReplyAsync for this turn */ }","preventionTips":["Don't request multimodal (image) output through GeminiMessageConnector","Upgrade AutoGen.Gemini when using newer Gemini part types"],"tags":["autogen","gemini","streaming","multimodal"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}