microsoft/semantic-kernel · error · FileNotFoundException

ApiManifest file not found: {filePath}

Error message

ApiManifest file not found: {filePath}

What it means

Thrown by ApiManifestKernelExtensions when the `filePath` passed to the ApiManifest plugin registration does not exist (File.Exists returns false). The method then attempts to load and parse the ApiManifest JSON, so it refuses to proceed on a missing file rather than letting the stream reader throw a less clear error.

Source

Thrown at dotnet/src/Functions/Functions.OpenApi.Extensions/Extensions/ApiManifestKernelExtensions.cs:111

    /// <returns>A task that represents the asynchronous operation. The task result contains the created kernel plugin.</returns>
    public static async Task<KernelPlugin> CreatePluginFromApiManifestAsync(
        this Kernel kernel,
        string pluginName,
        string filePath,
        string? description,
        ApiManifestPluginParameters? pluginParameters = null,
        CancellationToken cancellationToken = default)
    {
        Verify.NotNull(kernel);
        KernelVerify.ValidPluginName(pluginName, kernel.Plugins);

#pragma warning disable CA2000 // Dispose objects before losing scope. No need to dispose the Http client here. It can either be an internal client using NonDisposableHttpClientHandler or an external client managed by the calling code, which should handle its disposal.
        var httpClient = HttpClientProvider.GetHttpClient(pluginParameters?.HttpClient ?? kernel.Services.GetService<HttpClient>());
#pragma warning restore CA2000

        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException($"ApiManifest file not found: {filePath}");
        }

        var loggerFactory = kernel.LoggerFactory;
        var logger = loggerFactory.CreateLogger(typeof(ApiManifestKernelExtensions)) ?? NullLogger.Instance;
        using var apiManifestFileJsonContents = DocumentLoader.LoadDocumentFromFilePathAsStream(filePath,
            logger);
        JsonDocument jsonDocument = await JsonDocument.ParseAsync(apiManifestFileJsonContents, cancellationToken: cancellationToken).ConfigureAwait(false);

        ApiManifestDocument document = ApiManifestDocument.Load(jsonDocument.RootElement);

        var functions = new List<KernelFunction>();
        var documentWalker = new OpenApiWalker(new OperationIdNormalizationOpenApiVisitor());
        foreach (var apiDependency in document.ApiDependencies)
        {
            var apiName = apiDependency.Key;
            var apiDependencyDetails = apiDependency.Value;

            var apiDescriptionUrl = apiDependencyDetails.ApiDescriptionUrl;

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Verify File.Exists(filePath) before calling and log the resolved absolute path.
  2. Build the path from AppContext.BaseDirectory for deployed apps.
  3. Ensure the manifest is included as content copied to the output directory in your .csproj.

Example fix

// before
await kernel.CreatePluginFromApiManifestAsync(@"./apimanifest.json", "api");
// after
var path = Path.Combine(AppContext.BaseDirectory, "apimanifest.json");
await kernel.CreatePluginFromApiManifestAsync(path, "api");
Defensive patterns

Strategy: validation

Validate before calling

if (!File.Exists(filePath))
    throw new InvalidOperationException($"ApiManifest missing: {Path.GetFullPath(filePath)}");
await kernel.CreatePluginFromApiManifestAsync(filePath, pluginName);

Prevention

When it happens

Trigger: Calling `kernel.CreatePluginFromApiManifestAsync(filePath, pluginName)` with a wrong, relative-but-misresolved, or non-deployed ApiManifest file path.

Common situations: Path relative to the wrong working directory; manifest file not copied to output; typo in filename; environment-specific path that differs across machines.

Related errors


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