dotnet/reactive · error · InvalidOperationException

MORE_THAN_ONE_ELEMENT

Error message

MORE_THAN_ONE_ELEMENT

What it means

SingleAsync requires the source to emit exactly one element. On a second OnNext while a value was already seen, the operator throws InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT) and forwards it via OnError. This mirrors LINQ's Single() semantics for sequences with more than one element.

Solutions

  1. Ensure the stream emits exactly one value (use Take(1), FirstAsync, or .DistinctUntilChanged() if duplicates are identical).
  2. If multiple values are legitimate, use FirstAsync/LastAsync instead of SingleAsync.
  3. Handle the InvalidOperationException via OnError and fall back to First/Last semantics.

Example fix

// before
var value = await configLoaded.SingleAsync();
// after
var value = await configLoaded.Take(1).FirstAsync();
Defensive patterns

Strategy: fallback

Try / catch

try { var v = await source.SingleAsync(); }
catch (InvalidOperationException) { var v = await source.FirstAsync(); }

Prevention

When it happens

Trigger: source.SingleAsync() subscribed to a stream that emits two or more OnNext values before completing.

Common situations: Assuming an event fires once (e.g. 'configuration loaded') but it fires on reloads; hot observables or subjects receiving multiple pushes; debounce/missing distinct logic letting duplicates through.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/32771bfc523210e0. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs:38

            protected override void Run(_ sink) => sink.Run(_source);

            internal sealed class _ : IdentitySink<TSource>
            {
                private TSource? _value;
                private bool _seenValue;

                public _(IObserver<TSource> observer)
                    : base(observer)
                {
                }

                public override void OnNext(TSource value)
                {
                    if (_seenValue)
                    {
                        try
                        {
                            throw new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT);
                        }
                        catch (Exception e)
                        {
                            ForwardOnError(e);
                        }
                        return;
                    }

                    _value = value;
                    _seenValue = true;
                }

                public override void OnCompleted()
                {
                    if (!_seenValue)
                    {
                        try
                        {

View on GitHub (pinned to 94b5d5ab91)