microsoft/semantic-kernel · error · KernelException

Parsing of OpenAPI document failed.

Error message

Parsing of OpenAPI document failed.

What it means

Thrown by OpenApiDocumentParser.DowngradeDocumentVersionToSupportedOneAsync when ConvertContentToJsonAsync returns null. That helper deserializes the stream as YAML/JSON via SharpYaml then re-parses to a JsonObject; a null result means the deserializer could not produce any object - the stream was empty, contained only non-document content, or was unreadable.

Source

Thrown at dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs:96

        "text/plain"
    ];

    private readonly OpenApiStreamReader _openApiReader = new();
    private readonly ILogger _logger = loggerFactory?.CreateLogger(typeof(OpenApiDocumentParser)) ?? NullLogger.Instance;

    /// <summary>
    /// Downgrades the version of an OpenAPI document to the latest supported one - 3.0.1.
    /// This class relies on Microsoft.OpenAPI.NET library to work with OpenAPI documents.
    /// The library, at the moment, does not support 3.1 spec, and the latest supported version is 3.0.1.
    /// There's an open issue tracking the support progress - https://github.com/microsoft/OpenAPI.NET/issues/795
    /// This method should be removed/revised as soon the support is added.
    /// </summary>
    /// <param name="stream">The original OpenAPI document stream.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <returns>OpenAPI document with downgraded document version.</returns>
    private async Task<JsonObject> DowngradeDocumentVersionToSupportedOneAsync(Stream stream, CancellationToken cancellationToken)
    {
        var jsonObject = await ConvertContentToJsonAsync(stream, cancellationToken).ConfigureAwait(false) ?? throw new KernelException("Parsing of OpenAPI document failed.");
        if (!jsonObject.TryGetPropertyValue(OpenApiVersionPropertyName, out var propertyNode))
        {
            // The document is either malformed or has 2.x version that specifies document version in the 'swagger' property rather than in the 'openapi' one.
            return jsonObject;
        }

        if (propertyNode is not JsonValue value)
        {
            // The 'openapi' property has unexpected type.
            return jsonObject;
        }

        if (!Version.TryParse(value.ToString(), out var version))
        {
            // The 'openapi' property is malformed.
            return jsonObject;
        }

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Reset the stream position to 0 before parsing if it was previously read (stream.Position = 0).
  2. Verify the stream actually contains OpenAPI YAML/JSON - open and inspect the first bytes; check HTTP status if loaded from a URL.
  3. For HTTP-loaded specs, confirm the endpoint returns the document and not an error/redirect page.
  4. Ensure the stream is not empty and is left readable (not disposed/closed).

Example fix

// before - stream already consumed, Position at end
using var stream = File.OpenRead("openapi.yaml");
await new StreamReader(stream).ReadToEndAsync();
var spec = await parser.ParseAsync(stream);

// after - reset position before parsing
using var stream = File.OpenRead("openapi.yaml");
await new StreamReader(stream).ReadToEndAsync();
stream.Position = 0;
var spec = await parser.ParseAsync(stream);
Defensive patterns

Strategy: validation

Validate before calling

if (stream.CanSeek && stream.Position != 0) stream.Position = 0;
if (stream.Length == 0) throw new InvalidDataException("OpenAPI stream is empty.");
using var reader = new StreamReader(stream, leaveOpen: true);
var first = reader.Peek();
if (first == -1) throw new InvalidDataException("OpenAPI stream is unreadable.");

Type guard

static bool StreamLooksLikeDocument(Stream s)
{ if (!s.CanRead) return false; if (s.CanSeek && s.Position != 0) s.Position = 0; using var r = new StreamReader(s, leaveOpen:true); return r.Peek() != -1; }

Try / catch

try { var spec = await parser.ParseAsync(stream, options, ct); }
catch (KernelException ex) when (ex.Message == "Parsing of OpenAPI document failed.")
{ logger.LogError(ex, "Stream could not be parsed as YAML/JSON; check it is non-empty and valid."); throw; }

Prevention

When it happens

Trigger: Passing an empty stream to the parser; a stream whose content is not valid YAML or JSON (e.g. HTML error page, binary, garbage); a stream whose position is at the end (already consumed) so Deserialize returns null; a YAML document with only comments/whitespace.

Common situations: Loading an OpenAPI spec from a stream that was already read and not reset to position 0; pointing at a URL that returns an HTML 404 instead of a spec; an empty or truncated file; a content-type mismatch where the bytes are not actually YAML/JSON.

Related errors


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