Debugging System.AggregateException - even in async code
Tags: csharp, dotnet
Published: 2020-09-23 07:57:27

---
title: Debugging System.AggregateException - even in async code
published: true
description: Learn everything about how to debug async errors in C# like: Exception thrown System.AggregateException in mscorlib.dll - a task was canceled.
tags: csharp, dotnet
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/g2cxss19u2tgxdm9ls2v.png
canonical_url: https://blog.elmah.io/debugging-system-aggregateexception-even-in-async-code/
---

I'm here once again to help you debug common .NET exceptions. This time I want to help you debug the rather generic System.AggregateException. As the name implies, AggregateException is used to batch one or more exceptions together in a single exception. In this post, I'll show you why this exception occurs and how to debug it in your C# code.

## Causing and handling the error

Let's start by forcing a new `AggregateException`. The exception is used heavily in .NET's Task libraries, why choosing an example involving tasks is a no-brainer:

```csharp
Task task1 = Task.Factory.StartNew(() => { throw new ArgumentException(); } );
Task task2 = Task.Factory.StartNew(() => { throw new UnauthorizedAccessException(); } );

try
{
    Task.WaitAll(task1, task2);
}
catch (AggregateException ae)
{
}
```

In the example above, we spin up two tasks, each throwing an exception. By calling `WaitAll` we tell .NET to invoke and wait for an result from each of the two tasks. The combined result of the two tasks will be an `AggregateException`.

You've probably come to this article because of one of the following error messages:

- System.AggregateException: One or more errors occurred.
- A task was cancelled
- 'System.AggregateException' occurred in mscorlib.dll

In the following section I will show you how to debug and fix each.

## Debugging the error

When inspecting the exception from the previous example in the debugger, we see the two thrown exceptions in the `InnerExceptions` property:

![](https://blog.elmah.io/content/images/2019/05/aggregate-exception-with-inner-exceptions.png)

Just as promised in the name, `AggregateException` is a wrapper of other exceptions. In the example, both the `ArgumentException` and the `UnauthorizedAccessException` is available as inner exceptions.

In some scenarios you would add a catch blog per exception like this:

```csharp
try
{
    ...
}
catch (ArgumentException ex1)
{
    // Log and re-throw
}
catch (UnauthorizedAccessException ex2)
{
    // Log and swallow
}
```

This way, you can generate individual error messages to the user, log the exception but only re-throw one of them, or something third. Rather than looping over each exception in the `InnerExceptions` property, `AggregateException` provides a handy little helper method named `Handle`:

```csharp
try
{
    ...
}
catch (AggregateException ae)
{
    ae.Handle(inner =>
    {
        // Log inner
        ...
        return inner is UnauthorizedAccessException;
    });
}
```

In the example, the `Handle` method logs each exception. The `func` needs to return a `bool` indicating if each exception has been handled. In this case, we tell the `Handle` method that the `UnauthorizedAccessException` is handled, but not the `ArgumentException`. This will cause the `AggregateException` to be thrown back to the calling code, but without the `UnauthorizedAccessException` in the `InnerExceptions` property (because we marked that exception as already handled).

## AggregateExceptions from HttpClient

When dealing with the `System.Net.Http.HttpClient` class, you may experience the `AggregateException`. This is mostly when implementing async code using the old API (`Wait`, `ContinueWith`, etc.). Let's look at an example:

```csharp
try
{
    var client = new HttpClient();
    var task = client.GetStringAsync("https://httpstat.us/500");
    task.Wait();
    var result = task.Result;
}
catch (AggregateException ex)
{
    throw ex;
}
```

The request to `https://httpstat.us/500` returns a HTTP status code of `500` which throws a `HttpRequestException`. I'm using the `GetStringAsync` method as an example, but the code would look similar if using other async messages like `PostAsync`. As we saw previously, exceptions from the tasks API are wrapped in an `AggregateException`, containing the HTTP exception in the `InnerExceptions` property.

To get the actual exception, you have a range of options. I'll re-use the need for logging the exception to illustrate. Let's start with the Handle method I showed you in a previous example:

```csharp
try
{
    ...
}
catch (AggregateException ex)
{
    ex.Handle(inner =>
    {
        if (inner is HttpRequestException)
        {
            // Log the exception
            
            return true;
        }
        
        return false;
    });
}
```

I'm checking if the inner exception is of type `HttpRequestException` and in that case tell the `Handle` method that this exception has been handled. In any other scenario, I tell `Handle` to re-throw the original exception (by returning `false`).

Another approach will be to use the `ContinueWith` method to catch and handle the `AggregateException`:

```csharp
var client = new HttpClient();
var task = client
    .GetStringAsync("https://httpstat.us/500")
    .ContinueWith(t =>
    {
        try
        {
            return t.Result;
        }
        catch (AggregateException ex)
        {
            ex.Handle(inner =>
            {
                if (inner is HttpRequestException)
                {
                    // Log the exception

                    return true;
                }

                return false;
            });
        }
        catch (Exception ex)
        {
            throw ex;
        }

        return null;
    });
task.Wait();
var result = task.Result;
```

I've basically just moved the try catch from before inside the `ContinueWith` method.

Finally, if you are on .NET 4.5 (you probably are and if not, you should be) you can use the `await` keyword:

```csharp
var client = new HttpClient();
try
{
    var result = await client.GetStringAsync("https://httpstat.us/500");
}
catch (HttpRequestException ex)
{
    // Log the exception
}
catch (Exception ex)
{
    throw ex;
}

```

Notice how the code catches `HttpRequestException` instead of `AggregateException`. This is because .NET automatically unwraps the `AggregateException` and throw the underlying exception instead. This is what you want in most cases. Yet another benefit of porting existing async code to use the `await` keyword.

Also make sure to read the other posts in this series: [Debugging common .NET exceptions](https://blog.elmah.io/tag/common-exceptions/).

## Would your users appreciate fewer errors?

elmah.io is the easy error logging and uptime monitoring service for .NET. Take back control of your errors with support for all .NET web and logging frameworks.

➡️ [Error Monitoring for .NET Web Applications](https://elmah.io/?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) ⬅️

This article first appeared on the elmah.io blog at https://blog.elmah.io/debugging-system-aggregateexception-even-in-async-code/