{"record":{"id":"6cb9de5d62447ade","repo":"microsoft/semantic-kernel","slug":"parsing-of-openapi-document-failed","errorCode":null,"errorMessage":"Parsing of OpenAPI document failed.","messagePattern":"Parsing of OpenAPI document failed\\.","errorType":"exception","errorClass":"KernelException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs","lineNumber":96,"sourceCode":"        \"text/plain\"\n    ];\n\n    private readonly OpenApiStreamReader _openApiReader = new();\n    private readonly ILogger _logger = loggerFactory?.CreateLogger(typeof(OpenApiDocumentParser)) ?? NullLogger.Instance;\n\n    /// <summary>\n    /// Downgrades the version of an OpenAPI document to the latest supported one - 3.0.1.\n    /// This class relies on Microsoft.OpenAPI.NET library to work with OpenAPI documents.\n    /// The library, at the moment, does not support 3.1 spec, and the latest supported version is 3.0.1.\n    /// There's an open issue tracking the support progress - https://github.com/microsoft/OpenAPI.NET/issues/795\n    /// This method should be removed/revised as soon the support is added.\n    /// </summary>\n    /// <param name=\"stream\">The original OpenAPI document stream.</param>\n    /// <param name=\"cancellationToken\">The cancellation token.</param>\n    /// <returns>OpenAPI document with downgraded document version.</returns>\n    private async Task<JsonObject> DowngradeDocumentVersionToSupportedOneAsync(Stream stream, CancellationToken cancellationToken)\n    {\n        var jsonObject = await ConvertContentToJsonAsync(stream, cancellationToken).ConfigureAwait(false) ?? throw new KernelException(\"Parsing of OpenAPI document failed.\");\n        if (!jsonObject.TryGetPropertyValue(OpenApiVersionPropertyName, out var propertyNode))\n        {\n            // The document is either malformed or has 2.x version that specifies document version in the 'swagger' property rather than in the 'openapi' one.\n            return jsonObject;\n        }\n\n        if (propertyNode is not JsonValue value)\n        {\n            // The 'openapi' property has unexpected type.\n            return jsonObject;\n        }\n\n        if (!Version.TryParse(value.ToString(), out var version))\n        {\n            // The 'openapi' property is malformed.\n            return jsonObject;\n        }\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs#L78-L114","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reset the stream position to 0 before parsing if it was previously read (stream.Position = 0).","Verify the stream actually contains OpenAPI YAML/JSON - open and inspect the first bytes; check HTTP status if loaded from a URL.","For HTTP-loaded specs, confirm the endpoint returns the document and not an error/redirect page.","Ensure the stream is not empty and is left readable (not disposed/closed)."],"exampleFix":"// before - stream already consumed, Position at end\nusing var stream = File.OpenRead(\"openapi.yaml\");\nawait new StreamReader(stream).ReadToEndAsync();\nvar spec = await parser.ParseAsync(stream);\n\n// after - reset position before parsing\nusing var stream = File.OpenRead(\"openapi.yaml\");\nawait new StreamReader(stream).ReadToEndAsync();\nstream.Position = 0;\nvar spec = await parser.ParseAsync(stream);","handlingStrategy":"validation","validationCode":"if (stream.CanSeek && stream.Position != 0) stream.Position = 0;\nif (stream.Length == 0) throw new InvalidDataException(\"OpenAPI stream is empty.\");\nusing var reader = new StreamReader(stream, leaveOpen: true);\nvar first = reader.Peek();\nif (first == -1) throw new InvalidDataException(\"OpenAPI stream is unreadable.\");","typeGuard":"static bool StreamLooksLikeDocument(Stream s)\n{ 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; }","tryCatchPattern":"try { var spec = await parser.ParseAsync(stream, options, ct); }\ncatch (KernelException ex) when (ex.Message == \"Parsing of OpenAPI document failed.\")\n{ logger.LogError(ex, \"Stream could not be parsed as YAML/JSON; check it is non-empty and valid.\"); throw; }","preventionTips":["Reset stream.Position to 0 before parsing if previously read.","Verify HTTP-loaded specs return 200 with YAML/JSON content, not an error page.","Confirm the file is non-empty and genuinely OpenAPI."],"tags":["openapi","parsing","stream","yaml","json"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}