dotnet/reactive · error · InvalidOperationException

Sequence contains no elements.

Error message

Sequence contains no elements.

What it means

The ToTask/LastAsync observer's OnCompleted throws InvalidOperationException("Sequence contains no elements.") when the observable completes without emitting any value while being converted to a task that expects a Last value. The exception is routed into the returned Task, which becomes faulted.

Solutions

  1. Use .DefaultIfEmpty(defaultValue).ToTask() so an empty sequence yields a default.
  2. Await the task inside try/catch of InvalidOperationException when empty is acceptable.
  3. Use FirstAsync/FirstOrDefaultAsync semantics instead of Last/ToTask when a single element may not exist.
  4. Fix the upstream source to emit at least one value.

Example fix

// before
var result = await source.ToTask();
// after
var result = await source.DefaultIfEmpty(defaultValue).ToTask();
Defensive patterns

Strategy: fallback

Validate before calling

var isEmpty = await source.IsEmptyAsync();
var task = isEmpty ? Task.FromResult(defaultValue) : source.ToTask();

Try / catch

try { result = await source.ToTask(); }
catch (InvalidOperationException) { result = defaultValue; }

Prevention

When it happens

Trigger: Calling observable.ToTask() or LastAsync on an observable that completes with zero OnNext emissions.

Common situations: Empty source sequences, fully filtered streams, or early-completed streams due to cancellation/dispose before the first element.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Threading/Tasks/TaskObservableExtensions.cs:557

            public override void OnError(Exception error)
            {
                _tcs.TrySetException(error);

                _ctr.Dispose(); // no null-check needed (struct)
                Dispose();
            }

            public override void OnCompleted()
            {
                if (_hasValue)
                {
                    _tcs.TrySetResult(_lastValue!);
                }
                else
                {
                    try
                    {
                        throw new InvalidOperationException(Strings_Linq.NO_ELEMENTS);
                    }
                    catch (Exception e)
                    {
                        _tcs.TrySetException(e);
                    }
                }

                _ctr.Dispose(); // no null-check needed (struct)
                Dispose();
            }

            private void Cancel()
            {
                Dispose();
                _tcs.TrySetCanceled(_ct);
            }
        }

View on GitHub (pinned to 94b5d5ab91)