microsoft/semantic-kernel · error · NotSupportedException

Unsupported function choice '{config.Choice}'.

Error message

Unsupported function choice '{config.Choice}'.

What it means

Thrown in the tool-choice branch of ConfigureFunctionCalling. After mapping FunctionChoice.Auto/Required/None to the corresponding ChatToolChoice, the else branch catches any FunctionChoice enum value not handled (e.g. a future member or an invalid integer cast to FunctionChoice). The unsupported value is reported.

Source

Thrown at dotnet/src/Connectors/Connectors.OpenAI/Core/ClientCore.ChatCompletion.cs:1349

        bool autoInvoke = config?.AutoInvoke ?? false;

        if (config?.Functions is { Count: > 0 } functions)
        {
            if (config.Choice == FunctionChoice.Auto)
            {
                toolChoice = ChatToolChoice.CreateAutoChoice();
            }
            else if (config.Choice == FunctionChoice.Required)
            {
                toolChoice = ChatToolChoice.CreateRequiredChoice();
            }
            else if (config.Choice == FunctionChoice.None)
            {
                toolChoice = ChatToolChoice.CreateNoneChoice();
            }
            else
            {
                throw new NotSupportedException($"Unsupported function choice '{config.Choice}'.");
            }

            tools = [];

            foreach (var function in functions)
            {
                tools.Add(function.Metadata.ToOpenAIFunction().ToFunctionDefinition(config?.Options?.AllowStrictSchemaAdherence ?? false));
            }
        }

        return new(tools, toolChoice, autoInvoke, config?.Options);
    }

    /// <summary>
    /// Processes non-function tool calls.
    /// </summary>
    /// <param name="toolCalls">All tool calls requested by AI model.</param>
    /// <param name="chatHistory">The chat history.</param>

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Use FunctionChoice.Auto, Required, or None only.
  2. If a new FunctionChoice member is needed, upgrade Connectors.OpenAI to a version that maps it.
  3. Do not cast arbitrary integers to FunctionChoice.

Example fix

// before
var cfg = new FunctionChoiceBehaviorConfig { Choice = (FunctionChoice)42 };
// after
var cfg = new FunctionChoiceBehaviorConfig { Choice = FunctionChoice.Auto };
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<FunctionChoice> ValidChoices = new() { FunctionChoice.Auto, FunctionChoice.Required, FunctionChoice.None };
static void EnsureChoice(FunctionChoice c) { if (!ValidChoices.Contains(c)) throw new ArgumentException($"FunctionChoice {c} not mapped"); }

Type guard

static bool IsValidFunctionChoice(FunctionChoice c) => ValidChoices.Contains(c);

Try / catch

try { await client.GetChatCompletionAsync(...); }
catch (NotSupportedException ex) when (ex.Message.Contains("function choice")) { /* fall back to FunctionChoice.Auto and retry */ }

Prevention

When it happens

Trigger: config.Choice is a FunctionChoice value other than Auto, Required, or None — for example a newly added enum member not yet mapped by this connector build, or an integer cast like (FunctionChoice)99.

Common situations: Version skew between the FunctionChoice enum source and the connector; reflection/deserialization forcing an out-of-range enum value.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/3c74b2fc9a58e5c2. Report an issue: GitHub.