diff --git a/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonReaderExtensions.cs b/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonReaderExtensions.cs index 98fa0bee058..cd34dae2c9a 100644 --- a/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonReaderExtensions.cs +++ b/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonReaderExtensions.cs @@ -63,6 +63,29 @@ public static JsonException UnexpectedTokenException(this ref Utf8JsonReader rea return new JsonException($"Expected JSON {valid} token, but got '{reader.TokenType}'."); } + public static void SafeSkip(this ref Utf8JsonReader reader) + { + // Utf8JsonReader.Skip() unconditionally throws, if the reader instance is constructed with `isFinalBlock = false`. + // This may happen when reading from streams or pipes. + + // For custom converters, System.Text.JSON always guarantees that the entire JSON value for the current scope is available. + // See: + // https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to#steps-to-follow-the-basic-pattern + + // > Override the Read method to deserialize the incoming JSON and convert it to type T. Use the Utf8JsonReader that's passed to + // > the method to read the JSON. You don't have to worry about handling partial data, as the serializer passes all the data for + // > the current JSON scope. + + // We use `TrySkip()` here to avoid the exception. + + if (!reader.TrySkip()) + { + throw new InvalidOperationException( + "Failed to skip JSON token. This case should never happen and indicates a severe problem. " + + "Please open an issue in the Github repository."); + } + } + /// /// Compares the JSON encoded text to the JSON token value in the source and returns if they match. /// diff --git a/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonUnionSelector.cs b/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonUnionSelector.cs index 32c24291900..6d7126d2b5d 100644 --- a/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonUnionSelector.cs +++ b/src/Elastic.Clients.Elasticsearch/_Shared/Next/JsonUnionSelector.cs @@ -119,7 +119,7 @@ public static UnionTag MatchProperty(ref Utf8JsonReader reader, JsonSerializerOp } internalReader.Read(); - internalReader.Skip(); + internalReader.SafeSkip(); } return UnionTag.None; diff --git a/src/Elastic.Clients.Elasticsearch/_Shared/Types/Core/Bulk/BulkResponseItemConverter.cs b/src/Elastic.Clients.Elasticsearch/_Shared/Types/Core/Bulk/BulkResponseItemConverter.cs index cb6835579e7..234753b4eca 100644 --- a/src/Elastic.Clients.Elasticsearch/_Shared/Types/Core/Bulk/BulkResponseItemConverter.cs +++ b/src/Elastic.Clients.Elasticsearch/_Shared/Types/Core/Bulk/BulkResponseItemConverter.cs @@ -108,7 +108,7 @@ public override ResponseItem Read(ref Utf8JsonReader reader, Type typeToConvert, if (options.UnmappedMemberHandling is JsonUnmappedMemberHandling.Skip) { - reader.Skip(); + reader.SafeSkip(); continue; }