-
Notifications
You must be signed in to change notification settings - Fork 524
Description
We have received multiple reports of cases where the SDK throws a JSON serialization exception when processing HTTP responses from the Cosmos DB Gateway, for example:
Exception: Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Path '', line 0, position 0.
at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)
at Microsoft.Azure.Documents.JsonSerializable.LoadFrom(JsonReader reader, JsonSerializerSettings serializerSettings)
at Microsoft.Azure.Documents.JsonSerializable.LoadFrom[T](JsonTextReader jsonReader, ITypeResolver`1 typeResolver, JsonSerializerSettings settings)
at Microsoft.Azure.Cosmos.GatewayStoreClient.<CreateDocumentClientExceptionAsync>d__11.MoveNext() --- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.Azure.Cosmos.GatewayStoreClient.<ParseResponseAsync>d__9.MoveNext()
Microsoft.Azure.Cosmos.GatewayStoreClient.<ParseResponseAsync> hints as this being an HTTP response from Gateway.
Microsoft.Azure.Cosmos.GatewayStoreClient.<CreateDocumentClientExceptionAsync> means the statuscode of the HTTP response was a failure (not 200 or any success).
Which means, Gateway returned a failure but the content was invalid.
SDK checks the Content-Type header and if it's application/json then expects the content to be valid JSON:
azure-cosmos-dotnet-v3/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs
Lines 151 to 154 in 083df87
| if (string.Equals(responseMessage.Content?.Headers?.ContentType?.MediaType, "application/json", StringComparison.OrdinalIgnoreCase)) | |
| { | |
| Stream readStream = await responseMessage.Content.ReadAsStreamAsync(); | |
| Error error = Documents.Resource.LoadFrom<Error>(readStream); |
In all these cases what happened was that the content was either empty or invalid JSON.
To avoid the exception in the most common case (empty), we should check the Content-Size of the response, and if it's 0, either throw an exception saying that the response is invalid because it's empty or avoid attempting the JSON deserialization of the body and just produce the error response using the statuscode as if it had no content.
Expected outcome
- If the Content-Size header is
application/jsonbut the content size is 0, skip attempting to deserialize the content - If the Content-Size header is
application/jsonbut the content size > 0, attempt to deserialize the content. If that fails, follow the code path that treats the content as text (non-JSON path).
Metadata
Metadata
Assignees
Labels
Type
Projects
Status