shawnmclean / Mandrill-dotnet

.NET wrapper for Mandrill
Other
202 stars 107 forks source link

JSON Error deserializing Mandrill response #169

Closed RPM1984 closed 8 years ago

RPM1984 commented 8 years ago

Hey guys,

Every now and then, i get this error:

at Newtonsoft.Json.JsonTextReader.ParseValue() 
at Newtonsoft.Json.JsonTextReader.Read() 
at Newtonsoft.Json.JsonReader.ReadAndMoveToContent() 
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter) 
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) 
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) 
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) 
at Mandrill.MandrillApi.d__2c`1.MoveNext() 

--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Mandrill.MandrillApi.d__22.MoveNext() 
Exception Message: Unexpected character encountered while parsing value: <. path '', line 0, position 0.. stack trace: 
at newtonsoft.json.jsontextreader.parsevalue() newtonsoft.json.jsontextreader.read() newtonsoft.json.jsonreader.readandmovetocontent() newtonsoft.json.serialization.jsonserializerinternalreader.readfortype(jsonreader reader, jsoncontract contract, boolean hasconverter) newtonsoft.json.serialization.jsonserializerinternalreader.deserialize(jsonreader type objecttype, checkadditionalcontent) newtonsoft.json.jsonserializer.deserializeinternal(jsonreader objecttype) newtonsoft.json.jsonconvert.deserializeobject(string value, type, jsonserializersettings settings) newtonsoft.json.jsonconvert.deserializeobject[t](string mandrill.mandrillapi.d__2c`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown ---
 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Mandrill.MandrillApi.d__22.MoveNext() One or more errors occurred.. Stack Trace: at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at 

Basically, the pertinent line is this:

Exception Message: Unexpected character encountered while parsing value: <. path '', line 0, position 0.. stack trace: 

It feels like there's a Mandrill error, where an error page is shown (HTML? hence the <) and this library is trying to deserialize that into a POCO, and failing.

Any ideas?

If my predictions are correct, i would have thought the library would check for an error code before attempting to de-serialize?

I can see some code like that here but i'm not sure if that's whats being called.

tetsuo13 commented 8 years ago

Also started seeing these:

Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.

RPM1984 commented 8 years ago

@tetsuo13 good, so its not just me then!

tetsuo13 commented 8 years ago

I've got a modified version of an application which uses this library to save the exact payload from Mandrill to disk. Hopefully the next time this error comes up I can refer to it to see what Mandrill's Webhooks are sending and we can go from there.

RPM1984 commented 8 years ago

@tetsuo13 great idea. Please share here once you have it. Thanks!

shawnmclean commented 8 years ago

It should throw an an exception from the json.net library if html is returned from mandrill. It could be that the response came back as unsuccessful and its trying to deserialize an error response.

RPM1984 commented 8 years ago

@shawnmclean yes, but why. I would have thought the library should ensure status code of success before attempting to deserialize into the POCO. Basically, it's fine that Mandrill may error - but the consuming code should know that (and therefore, handle it accordingly). Right now the consuming code has no idea what's happening.

shawnmclean commented 8 years ago

Yea, I'm going to update it. The code is assuming that when an error comes back from mandrill, the content is in a json error format.

shawnmclean commented 8 years ago

I'd like to know what the html content thats coming back if anyone has it.

RPM1984 commented 8 years ago

Cool, thanks @shawnmclean

I can't give you the HTML error, because the library is swallowing it :smile:

Maybe @tetsuo13 has it.

shawnmclean commented 8 years ago

Released in 2.4.1. It catches serialization errors and pass on the request and response in the exception.

Let me know if that helps.

RPM1984 commented 8 years ago

@shawnmclean will try it out. Thanks for the quick turnaround!

Scotty79 commented 8 years ago

Just got this error as well. Haven't tried 2.4.1 yet as we are mid way through a large email campaign. Any one know if Mandrill are aware they are returning invalid JSON occasionally?

Scotty79 commented 7 years ago

Here's a response from Mandrill support Mar 18, 2016...

Thanks for writing back and providing that info. Generally, if your API call failed or was successful we'd return a JSON formatted response to the POST request. There can be occasions however, if our relays have received your request, but have issues passing that request to our app servers for processing that they may return a 502 Bad Gateway, or 504 Gateway Time-out type response. That error would be returned as an HTML message (along with the actual HTTP status code). So it's possible that these times you're seeing these errors in your system where your code was unable to parse the response received that there was an error that resulted in non-JSON content being returned — since the response is coming straight from the HTTP server, not our app servers in response to the API call. What I can tell you right now is that it looks like due to some increased volume we've been seeing, our app servers aren't always responding to our regional relays before the timeout period and so the relays may return a 502 bad gateway, or 504 gateway time-out error to you. So, if that's the case, it has nothing to do with your API calls or system that is sending those. For the time being I'd advise you to set up a retry mechanism for those occasions that you do see one of these errors. If our API returns anything other than a 200 response then you can reliably assume that those message won't be sent to your recipients. I'm going to ask our developers to take a look at this with me to see if they can spot anything. I'll follow up with you here as soon as I have some more info for you.

Scotty79 commented 7 years ago

We are using release 2.4.181 and it looks like this is still an issue today unfortunately. We've wrapped our SendMessage call in a Polly WaitAndRetryAsync policy which has helped us retry when general network exceptions occur. About to test retrying on Newtonsoft.Json.JsonReaderException as we are currently blasting over 1.3 million emails, so the chances of this happening again are fairly high :)

shawnmclean commented 7 years ago

@Scotty79 Thanks for sharing the Mandrill support response, that is useful information. I'll try to factor them in the failure code sometime this week.

Elviszip commented 3 years ago

still and issue

PureKrome commented 1 year ago

Cast "raise undead issue/169"

So here's the deal:

<html><body><h1>504 Gateway Time-out</h1>
The server didn't respond in time.
</body></html>

Winner Winner Chicken Dinner.

So the code should be updated to

giammin commented 1 year ago

why this issue is closed? it is still happening