Fix: Semantic Kernel Plugin and Function Registration Errors in .NET

From GitHub Issue .NET 9 Microsoft.SemanticKernel 1.34.0
By Rajesh Mishra · Feb 28, 2026 · Verified: Feb 28, 2026 · 7 min read

The Errors

Semantic Kernel plugin issues produce several different error messages depending on where the failure occurs.

Error 1: Function not found

Microsoft.SemanticKernel.KernelException:
Function 'WeatherPlugin-GetCurrentWeather' not found.

Error 2: Plugin not registered

System.Collections.Generic.KeyNotFoundException:
The given key 'WeatherPlugin' was not present in the dictionary.

Error 3: Runtime invocation failure

Microsoft.SemanticKernel.KernelException:
Error occurred while invoking function 'WeatherPlugin-GetCurrentWeather'.
---> System.InvalidOperationException:
Unable to convert parameter 'temperature' from System.Text.Json.JsonElement to System.Double.

All three errors lead to the same outcome: the kernel cannot call the function you intended. The fix depends on which part of the registration and invocation pipeline broke.

Root Cause 1: Missing [KernelFunction] Attribute

Semantic Kernel does not scan for methods automatically. Only methods decorated with [KernelFunction] are registered. This is the most common mistake, especially for developers coming from frameworks that use convention-based discovery.

Broken:

public class WeatherPlugin
{
    // Missing [KernelFunction] — this method is invisible to the kernel
    public string GetCurrentWeather(string city)
    {
        return $"The weather in {city} is 72°F and sunny.";
    }
}

Fixed:

using Microsoft.SemanticKernel;
using System.ComponentModel;

public class WeatherPlugin
{
    [KernelFunction("GetCurrentWeather")]
    [Description("Gets the current weather for a given city")]
    public string GetCurrentWeather(
        [Description("The city name, e.g. 'Seattle'")] string city)
    {
        return $"The weather in {city} is 72°F and sunny.";
    }
}

The [KernelFunction] attribute is the entry point for discovery. The [Description] attributes are not strictly required for manual invocation, but they are essential for AI function calling — the model reads these descriptions to decide when and how to call the function.

Root Cause 2: Non-Public Methods

Semantic Kernel only discovers public methods. Internal, protected, and private methods are silently skipped during registration. No warning is logged.

Broken:

public class MathPlugin
{
    [KernelFunction]
    internal double Add(double a, double b) => a + b;  // internal — not discovered
}

Fixed:

public class MathPlugin
{
    [KernelFunction("Add")]
    [Description("Adds two numbers together")]
    public double Add(
        [Description("First number")] double a,
        [Description("Second number")] double b) => a + b;
}

Root Cause 3: Plugin Not Registered with the Kernel

Writing the plugin class is only half the job. You must also add it to the kernel. There are several registration methods, and using the wrong one (or forgetting it entirely) leads to “not found” errors.

Option A: AddFromType (preferred for DI scenarios)

var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);
builder.Plugins.AddFromType<WeatherPlugin>();

var kernel = builder.Build();

This approach lets Semantic Kernel instantiate the plugin. If the plugin class has constructor dependencies, they are resolved from the kernel’s service provider.

Option B: AddFromObject (for pre-built instances)

var weatherPlugin = new WeatherPlugin(httpClient, logger);
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(deploymentName, endpoint, apiKey);
builder.Plugins.AddFromObject(weatherPlugin, "WeatherPlugin");

var kernel = builder.Build();

Use this when you need to control the plugin’s construction — passing specific dependencies, configuration, or a shared state object.

Option C: Import after building

var kernel = builder.Build();
kernel.ImportPluginFromType<WeatherPlugin>();

This works but means the plugin was not available during the builder phase. Prefer registration during builder setup for consistency.

Root Cause 4: Parameter Type Issues

When the AI model calls a function, it passes arguments as JSON. Semantic Kernel deserializes those into the method parameters. If the types are incompatible, invocation fails at runtime.

Common problems:

  • Using DateTime instead of string for date parameters (the model outputs dates as strings)
  • Using custom types without a JsonConverter
  • Using enum types without [Description] to tell the model the valid values

Broken:

[KernelFunction]
public string GetWeatherForDate(string city, DateTime date)  // DateTime parsing can fail
{
    // ...
}

Fixed:

[KernelFunction("GetWeatherForDate")]
[Description("Gets the weather forecast for a city on a specific date")]
public string GetWeatherForDate(
    [Description("City name")] string city,
    [Description("Date in ISO 8601 format, e.g. '2026-03-01'")] string date)
{
    var parsedDate = DateTime.Parse(date);
    // ...
}

Accept strings for dates and do the parsing yourself. This is more robust against the variety of date formats that language models produce.

Root Cause 5: Missing [Description] Attributes

Missing [Description] attributes do not cause hard errors. The plugin registers fine, and manual invocation works. But during automatic function calling, the AI model has no idea what the function does or what each parameter means. The function is effectively invisible to the model’s decision-making process.

Not enough:

[KernelFunction]
public string SearchDatabase(string query, int maxResults) { ... }

Production-ready:

[KernelFunction("SearchDatabase")]
[Description("Searches the product database and returns matching items")]
public string SearchDatabase(
    [Description("The search query, e.g. 'wireless headphones under $50'")] string query,
    [Description("Maximum number of results to return, between 1 and 20")] int maxResults)
{
    // ...
}

Detailed descriptions dramatically improve the model’s ability to select the right function and pass appropriate arguments.

Diagnostic: Inspecting Registered Plugins

When a function is not being found, verify what the kernel actually has registered:

var kernel = builder.Build();

foreach (var plugin in kernel.Plugins)
{
    Console.WriteLine($"Plugin: {plugin.Name}");
    foreach (var function in plugin)
    {
        Console.WriteLine($"  Function: {function.Name}");
        Console.WriteLine($"  Description: {function.Description}");

        foreach (var param in function.Metadata.Parameters)
        {
            Console.WriteLine($"    Param: {param.Name} ({param.ParameterType?.Name}) " +
                              $"- {param.Description}");
        }
    }
}

Run this at startup. If a function you expect is missing from the output, go back and check the attribute and visibility. This diagnostic loop takes milliseconds and saves hours of guessing.

Complete Working Example

Here is a properly configured plugin with automatic function calling:

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.AzureOpenAI;
using System.ComponentModel;

// 1. Define the plugin with proper attributes
public class TimePlugin
{
    [KernelFunction("GetCurrentTime")]
    [Description("Gets the current date and time in the specified timezone")]
    public string GetCurrentTime(
        [Description("IANA timezone identifier, e.g. 'America/New_York'")] string timezone)
    {
        try
        {
            var tz = TimeZoneInfo.FindSystemTimeZoneById(timezone);
            var time = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz);
            return $"Current time in {timezone}: {time:yyyy-MM-dd HH:mm:ss}";
        }
        catch (TimeZoneNotFoundException)
        {
            return $"Unknown timezone: {timezone}. Use IANA format like 'America/New_York'.";
        }
    }
}

// 2. Register and use it
var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
    deploymentName: config["AzureOpenAI:DeploymentName"]!,
    endpoint: config["AzureOpenAI:Endpoint"]!,
    apiKey: config["AzureOpenAI:ApiKey"]!);
builder.Plugins.AddFromType<TimePlugin>();

var kernel = builder.Build();

// 3. Enable automatic function calling
var settings = new AzureOpenAIPromptExecutionSettings
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

var chatService = kernel.GetRequiredService<IChatCompletionService>();
var history = new ChatHistory();
history.AddUserMessage("What time is it in Tokyo?");

var response = await chatService.GetChatMessageContentAsync(history, settings, kernel);
Console.WriteLine(response.Content);

Prevention Best Practices

  1. Add the diagnostic loop to your startup. Log all registered plugins and functions. This catches registration issues before any user request hits the system.
  2. Write unit tests for plugin registration. Create a test that builds the kernel, registers plugins, and asserts specific functions exist.
  3. Use descriptive names. The function name parameter in [KernelFunction("Name")] becomes the identifier the AI model sees. Make it clear and unambiguous.
  4. Keep parameter types simple. Strings, numbers, and booleans work reliably. For complex inputs, accept a JSON string parameter and deserialize it yourself.
  5. Handle exceptions inside plugin methods. A thrown exception during function invocation can crash the function-calling loop. Return error messages as strings instead.

Further Reading

⚠ Production Considerations

  • Missing [Description] attributes will not cause compile-time errors, but the AI model will not understand what the function does or what parameters it expects — leading to the function never being called during automatic function calling.
  • Plugins registered via AddFromType<T> are instantiated per-invocation unless you configure the DI container differently. Stateful plugins may lose state between calls.

🧠 Architect’s Note

For production plugin architectures, favor AddFromType<T> with proper DI lifetimes. Keep plugin methods focused on a single operation. Use the kernel's function call logging to audit which functions the model selects and why.

AI-Friendly Summary

Summary

Semantic Kernel plugin and function registration errors in .NET are caused by missing [KernelFunction] attributes, non-public methods, incorrect plugin registration calls, unsupported parameter types, or missing [Description] attributes. Fix by ensuring all plugin methods are public, decorated with [KernelFunction], and have [Description] on parameters used in AI function calling. Inspect registered plugins at runtime using kernel.Plugins to verify registration.

Key Takeaways

  • Every plugin method must be public and decorated with [KernelFunction] to be discoverable
  • Use [Description] on both the method and its parameters — the AI model uses these descriptions for function calling
  • Register plugins with AddFromType<T> for DI support or AddFromObject for pre-built instances
  • Inspect kernel.Plugins at runtime to verify what functions are actually registered
  • Return types must be serializable — avoid returning complex types without JSON serialization support

Implementation Checklist

  • Add [KernelFunction] attribute to every method intended as a kernel function
  • Add [Description] attribute to the method and each parameter
  • Ensure methods are public (not internal, protected, or private)
  • Register the plugin class using the correct AddFrom method
  • Verify registration by iterating kernel.Plugins at startup
  • Use supported parameter types (primitives, strings, enums) for AI function calling

Frequently Asked Questions

Why can't Semantic Kernel find my plugin function?

Semantic Kernel only discovers methods decorated with the [KernelFunction] attribute. If the attribute is missing, or if the method is not public, the kernel will not register it. Also verify that the plugin itself was added to the kernel via AddFromType, AddFromObject, or AddFromPromptDirectory.

Do I need the KernelFunction attribute?

Yes. The [KernelFunction] attribute is mandatory for Semantic Kernel to discover and register a method as an invocable function. Without it, the method is invisible to the kernel, even if the containing class is registered as a plugin.

How do I register a plugin in Semantic Kernel?

Use kernel.Plugins.AddFromType<MyPlugin>() for DI-compatible registration, kernel.Plugins.AddFromObject(new MyPlugin()) for instance-based registration, or kernel.ImportPluginFromPromptDirectory() for prompt-based plugins. Each method has different lifetime and dependency injection behavior.

Why does function invocation fail at runtime?

Runtime invocation failures are usually caused by unsupported parameter types, missing [Description] attributes on parameters (needed for AI function calling), parameters that cannot be deserialized from the AI model's JSON output, or exceptions thrown inside the function body itself.

Related Articles

Was this article useful?

Feedback is anonymous and helps us improve content quality.

Discussion

Engineering discussion powered by GitHub Discussions.

#Semantic Kernel #Plugin Errors #KernelFunction #.NET AI #Debugging