microsoft/semantic-kernel · error · InvalidCastException

The option key '{key}' value must be of type '{typeof(T)}' b

Error message

The option key '{key}' value must be of type '{typeof(T)}' but is '{value.GetType()}'.

What it means

Thrown by GetRequiredOption<T> when the option key exists and is non-null, but the value cannot be cast to the requested type T (the 'is T' pattern fails). It throws InvalidCastException, reporting both the expected and actual types. This usually means the agent definition supplied a scalar where a dictionary (or vice versa) was expected.

Source

Thrown at dotnet/src/Agents/AzureAI/Extensions/AgentToolDefinitionExtensions.cs:251

    private static T GetRequiredOption<T>(this AgentToolDefinition agentToolDefinition, string key)
    {
        Verify.NotNull(agentToolDefinition);
        Verify.NotNull(agentToolDefinition.Options);
        Verify.NotNull(key);

        if (agentToolDefinition.Options?.TryGetValue(key, out var value) ?? false)
        {
            if (value == null)
            {
                throw new ArgumentNullException($"The option key '{key}' must be a non null value.");
            }

            if (value is T expectedValue)
            {
                return expectedValue;
            }
            throw new InvalidCastException($"The option key '{key}' value must be of type '{typeof(T)}' but is '{value.GetType()}'.");
        }

        throw new ArgumentException($"The option key '{key}' was not found.");
    }

    private static readonly BinaryData s_noParams = BinaryData.FromObjectAsJson(new { type = "object", properties = new { } });
}

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Match the option value's shape to the expected type T (e.g., provide a nested mapping/object where a Dictionary<object,object> is required).
  2. Check the agent definition file's indentation/structure.
  3. Consult the tool's expected option schema for the exact type.

Example fix

// before (scalar where dict expected)
storage_queue: 'https://mystorage...'
// GetRequiredOption<Dictionary<object,object>> -> throws 168

// after (object)
storage_queue:
  storage_service_endpoint: https://mystorage.queue.core.windows.net
  queue_name: myqueue
Defensive patterns

Strategy: type-guard

Validate before calling

if (tool.Options != null && tool.Options.TryGetValue(key, out var v) && v is not null && v is not T)
    throw new InvalidOperationException($"Option '{key}' is {v.GetType()}, expected {typeof(T)}.");

Type guard

static bool OptionHasType<T>(AgentToolDefinition t, string key) =>
    t.Options is not null && t.Options.TryGetValue(key, out var v) && v is T;

Try / catch

try { var v = tool.GetRequiredOption<T>(key); }
catch (InvalidCastException ex) when (ex.Message.Contains(key))
{ /* coerce/fix the option value type, then retry */ }

Prevention

When it happens

Trigger: GetRequiredOption<Dictionary<object,object>>(bindingType) is called but the option value is a string; or GetRequiredOption<int> is given a string. The runtime type does not match T.

Common situations: Indentation/scoping bug in YAML produced a scalar instead of a mapping; JSON value is a string where an object was expected; version mismatch where a new type constraint was added.

Related errors


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