microsoft/autogen · error · InvalidOperationException

The response should contain exactly one candidate.

Error message

The response should contain exactly one candidate.

What it means

GeminiMessageConnector.ValidateGenerateContentResponse requires every GenerateContentResponse to carry exactly one candidate, because PostProcessMessage/PostProcessStreamingMessage index Candidates[0] unconditionally. If response.Candidates.Count is 0 (or >1) this InvalidOperationException is thrown before any part inspection.

Source

Thrown at dotnet/src/AutoGen.Gemini/Middleware/GeminiMessageConnector.cs:256

                return ProcessTextMessage(textMessage, agent);
            }

            return [];
        }
        else
        {
            var toolCallContents = ProcessToolCallMessage(toolCallAggregateMessage.Message1, agent);
            var toolCallResultContents = ProcessToolCallResultMessage(toolCallAggregateMessage.Message2, agent);

            return toolCallContents.Concat(toolCallResultContents);
        }
    }

    private void ValidateGenerateContentResponse(GenerateContentResponse response)
    {
        if (response.Candidates.Count != 1)
        {
            throw new InvalidOperationException("The response should contain exactly one candidate.");
        }

        var candidate = response.Candidates[0];
        if (candidate.Content is null)
        {
            var finishReason = candidate.FinishReason;
            var finishMessage = candidate.FinishMessage;

            throw new InvalidOperationException($"The response should contain content but the content is empty. FinishReason: {finishReason}, FinishMessage: {finishMessage}");
        }
    }

    private IEnumerable<IMessage> ProcessToolCallResultMessage(ToolCallResultMessage toolCallResultMessage, IAgent _)
    {
        var functionCallResultParts = new List<Part>();
        foreach (var toolCallResult in toolCallResultMessage.ToolCalls)
        {
            if (toolCallResult.Result is null)

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Inspect response.PromptFeedback.BlockReason for zero-candidate responses and adjust the prompt or SafetySettings.
  2. Ensure candidateCount is left at 1 in GenerateContentConfig — the connector cannot merge multiple candidates.
  3. Catch InvalidOperationException and treat it as a blocked/failed generation, falling back to a rephrased prompt.
  4. Upgrade AutoGen.Gemini for improved handling of blocked responses.

Example fix

// before
var config = new GenerateContentRequest { Config = new GenerateContentConfig { CandidateCount = 2 } };

// after
var config = new GenerateContentRequest { Config = new GenerateContentConfig { CandidateCount = 1 } };
Defensive patterns

Strategy: validation

Validate before calling

if (response.Candidates is null || response.Candidates.Count != 1)
{
    var block = response.PromptFeedback?.BlockReason;
    // treat as blocked/failed generation, do not call the connector
}

Try / catch

try { var reply = await geminiAgent.SendAsync(msg); } catch (InvalidOperationException ex) when (ex.Message.Contains("exactly one candidate")) { /* blocked prompt: rewrite and retry */ }

Prevention

When it happens

Trigger: Any GeminiAgent reply where the API returns zero candidates — typically when the prompt/request is blocked (safety, prohibited content, recitation) or the response is an error-ish payload with an empty candidate list; or a candidateCount > 1 configuration.

Common situations: Safety settings block the prompt (promptFeedback.blockReason set, candidates empty); requesting candidateCount > 1 in GenerateContentConfig; API version drift where blocked responses no longer include a placeholder candidate.

Related errors


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