louthy/language-ext · error · AggregateException

AggregateException from collected inner errors

Error message

AggregateException from collected inner errors

What it means

AsyncEnumerableEx.Merge aggregates the exceptions thrown by the merged source sequences; when any inner stream errors, the merge enumerates errors and throws a single AggregateException containing all collected inner errors at line 110. This is the library's way of reporting multiple concurrent stream failures from one Merge call. The real causes are the inner exceptions — inspect AggregateException.InnerExceptions.

Solutions

  1. Inspect ex.InnerExceptions on the AggregateException to handle each underlying failure
  2. Wrap the Merge consumption in try/catch (AggregateException) and decide per-inner-error whether to retry or drop
  3. Retry individual failing sources with backoff before merging, so Merge itself stays error-free
  4. Use error-tolerant sources (catch inside each source stream and yield a sentinel) so one failure doesn't fail the merge

Example fix

// before
await foreach (var x in AsyncEnumerableEx.Merge(srcA, srcB))
    Process(x); // throws AggregateException if either source fails
// after
try
{
    await foreach (var x in AsyncEnumerableEx.Merge(srcA, srcB))
        Process(x);
}
catch (AggregateException agg)
{
    foreach (var inner in agg.InnerExceptions)
        Log(inner); // handle/retry each failing source individually
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight each source with a guard
var safeA = srcA.Catch(ex => AsyncEnumerable.Empty<T>());
var safeB = srcB.Catch(ex => AsyncEnumerable.Empty<T>());
var merged = AsyncEnumerableEx.Merge(safeA, safeB);

Type guard

static bool HasInnerErrors(AggregateException agg) => agg.InnerExceptions.Count > 0;

Try / catch

try { await foreach (var x in merged) Process(x); }
catch (AggregateException agg)
{
    foreach (var inner in agg.InnerExceptions)
        HandleSourceError(inner); // retry/log per failing source
}

Prevention

When it happens

Trigger: Calling Merge (or Merge with a concurrency limit) where one or more of the merged IAsyncEnumerable sources throws while the merged sequence is being consumed; all inner errors are gathered and rethrown together as AggregateException.

Common situations: Merging several HTTP/stream/event sources where some fail mid-enumeration (network faults, upstream 5xx, canceled subscriptions); a partially failing fan-in pipeline; consuming Merge output without handling AggregateException.

Related errors


AI-assisted analysis of louthy/language-ext@2f0e362824 (2026-09-15). Data as JSON: /api/errors/b53385e72f45666e. Report an issue: GitHub.

Appendix: source

Thrown at LanguageExt.Core/Utility/AsyncEnumerableEx.cs:110

                            {
                                await enumerator.DisposeAsync().ConfigureAwait(false);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if (errors == null)
                        {
                            errors = new List<Exception>();
                        }

                        errors.Add(ex);
                    }
                }

                if (errors != null)
                {
                    throw new AggregateException(errors);
                }
            }
        }

    }

    /// <summary>
    /// Merges elements from all inner async-enumerable sequences into a single async-enumerable sequence.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
    /// <param name="sources">Async-enumerable sequence of inner async-enumerable sequences.</param>
    /// <returns>The async-enumerable sequence that merges the elements of the inner sequences.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
    public static IAsyncEnumerable<TSource> Merge<TSource>(
        this IAsyncEnumerable<IAsyncEnumerable<TSource>> sources) =>
        sources.SelectMany(source => source);
}

View on GitHub (pinned to 2f0e362824)