As traffic to our Azure website has increased, we've been seeing an increasing number of "A task was canceled" errors. A typical trace might look like this:
Fatal web api error: Controller: CustomerUserEventsController;
Url: http://app.payboard.com/api/organizations/9ddf55d1-e0c1-4a8f-9327-eef38682e090/addcustomeruserevent?callback=jQuery210035782216349616647_1398442710964&cookieId=05be2755-dc0d-414d-b0d2-ea1986a929c3&customerId=&customerName=&customerUserId=&customerUserFirstName=&customerUserLastName=&eventName=hr-index-GET&_=1398442710965;
Error: A task was canceled. ( at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext())
We used to maybe get one a day; it's been increasing gradually, so that now we're getting a couple dozen.
You'll notice that there's only framework code in the stack trace - none of our code is in there at all. So I'm a bit at a loss for how to troubleshoot it. Any suggestions on how to approach tracking these down?
When we occurred error "Task was cancelled", or large data request requirements. Another possibility is that the result is not awaited on the client side. This can happen if any one method on the call stack does not use the await keyword to wait for the call to be completed.
If the user navigates to another page, before these ajax requests complete, the requests are canceled by the browser. Our ELMAH HttpModule then logs two errors for each canceled request:
There's 2 likely reasons that a TaskCanceledException would be thrown: Something called Cancel () on the CancellationTokenSource associated with the cancellation token before the task completed. The request timed out, i.e. didn't complete within the timespan you specified on HttpClient.Timeout.
“ System.Threading.Tasks.TaskCanceledException: A task was canceled.” There could be multiple reasons for having this error. To find out the error root cause, you may need to analyze a few aspects. In my case, I was able to fix the issue by correcting the dependent HTTP API call which was failing due to Firewall issues.
See the answer here:
ASP.NET Web API OperationCanceledException when browser cancels the request
And the WebAPI bug here:
http://aspnetwebstack.codeplex.com/workitem/1797
Basically, it's expected when an HTTP request is canceled, for instance, if the user closes the page that initiated the request. To keep it from showing up in your logs, basically, you just need to create a custom message handler that suppresses the error:
/// <summary>
/// See https://stackoverflow.com/questions/22157596/asp-net-web-api-operationcanceledexception-when-browser-cancels-the-request
/// </summary>
public class CancelledTaskBugWorkaroundMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
// Try to suppress response content when the cancellation token has fired; ASP.NET will log to the Application event log if there's content in this case.
if (cancellationToken.IsCancellationRequested)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return response;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With