Skip to content

FetchNextPageAsync improperly throws an AggregateException #882

@jweber

Description

@jweber

Describe the bug

When using the FetchNextPageAsync method to retrieve an account's Subscriptions (using the ListAccountSubscriptions method), I get back an AggregateException where the InnerException property is the instance of Recurly.RecurlyError. I'd expect the actual Recurly.RecurlyError exception to be thrown rather than the AggrgateException since I'm awaiting the FetchNextPageAsync call.

To Reproduce

Here's a test that fails. The call to ListAccountsubscriptions should throw an NotFound exception, but throws an AggregateException with the InnerException being set to the NotFound exception.

[Test]
public async Task FetchNextPageAsync()
{
    var client = new Client(TestEnvironment.Settings.Recurly.ApiKey);

    // Set to an account that doesn't exist to trigger a `Recurly.Errors.NotFound` exception
    var pager = client.ListAccountSubscriptions("code-9999999999999");

    try
    {
        var page = await pager.FetchNextPageAsync();
    }
    // Gets hit
    catch (AggregateException e) when (e.InnerException is NotFound)
    {
        Assert.Fail("Expected NotFound exception, but got AggregateException with inner NotFound exception");
    }
    // Doesn't get hit
    catch (NotFound)
    {
        Assert.Pass();
    }
}

Expected behavior

Since the FetchNextPageAsync() method is being awaited here, an AggregateException is unexpected. In the example above, the NotFound exception should be thrown.

The fix for this is to await the call to MakeRequestAsync in the FetchNextPageAsync method, like so:

public async Task<Pager<T>> FetchNextPageAsync(CancellationToken cancellationToken = default(CancellationToken))
{
    Dictionary<string, object> NextParams = _pristine ? QueryParams : null;

    // New
    var pager = await RecurlyClient.MakeRequestAsync<Pager<T>>(Method.GET, Next, null, NextParams, Options, cancellationToken);
    this.Clone(pager);
    return this;

    // Old
    // var task = RecurlyClient.MakeRequestAsync<Pager<T>>(Method.GET, Next, null, NextParams, Options, cancellationToken);
    // return await task.ContinueWith(t =>
    // {
    //     var pager = t.Result;
    //     this.Clone(pager);
    //     return this;
    // });
}

Your Environment

  • Which version of this library are you using? 5.8.0
  • Which version of the language are you using? C# 13

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions