dotnet/reactive · error · InvalidOperationException
NO_MATCHING_ELEMENTS
Error message
NO_MATCHING_ELEMENTS
What it means
SingleAsync throws InvalidOperationException(NO_MATCHING_ELEMENTS) from its OnCompleted observer callback when the source completes without ever emitting a value. Single* operators require exactly one element; an empty sequence violates that contract, so the library signals the failure via OnError instead of returning a default. It is raised asynchronously during the terminal OnCompleted notification, not at subscription time.
Solutions
- Use SingleOrDefaultAsync instead of SingleAsync if an empty source is acceptable (it yields default(TSource)).
- Guard the sequence with .DefaultIfEmpty(...) before applying SingleAsync so OnCompleted always follows at least one value.
- Ensure upstream filtering cannot eliminate all elements, or handle the OnError(InvalidOperationException) explicitly in Subscribe.
- If the stream should never be empty, fix the producer that publishes zero elements.
Example fix
// before var value = await source.SingleAsync(); // throws when source is empty // after var value = await source.SingleOrDefaultAsync(); // default(TSource) when empty // or var value = await source.DefaultIfEmpty(fallback).SingleAsync();
Defensive patterns
Strategy: validation
Validate before calling
// Only call SingleAsync when the sequence is guaranteed non-empty
// e.g. check emptiness first:
bool hasAny = await source.Any(); // .Any() returns IObservable<bool>
if (!hasAny) { /* use default / report empty */ }
else var value = await source.SingleAsync(); Type guard
static bool HasExactlyOne<T>(IList<T> buffered) => buffered.Count == 1;
Try / catch
source.SingleAsync().Subscribe(
value => { /* use value */ },
ex => { if (ex is InvalidOperationException) { /* empty sequence path */ } else throw ex; }); Prevention
- Prefer SingleOrDefaultAsync whenever an empty source is plausible.
- Apply .DefaultIfEmpty(fallback) before SingleAsync for streams that may go empty.
- Assert producer contracts: a stream declared 'exactly one value' must not have filters added downstream that can empty it.
- Write a unit test feeding Observable.Empty<T>() through every Single* usage.
When it happens
Trigger: Calling Observable.SingleAsync(source) (or SingleAsync with a predicate) on a source that emits zero OnNext notifications before OnCompleted. The throw happens inside SingleAsync's observer.OnCompleted override at SingleAsync.cs:140 when _seenValue is still false.
Common situations: Subscribing to an empty observable (e.g. an empty array converted with ToObservable, a filtered stream that matches nothing, or a backend query returning no rows) and then expecting a single value; race conditions where an upstream filter becomes stricter and the stream can legitimately go empty.
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
- Strings_Linq.NO_ELEMENTS
- Strings_Linq.NO_ELEMENTS
- NO_ELEMENTS
- MORE_THAN_ONE_ELEMENT
- MORE_THAN_ONE_MATCHING_ELEMENT
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/337458dea7d8193e.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleAsync.cs:140
catch (Exception e)
{
ForwardOnError(e);
}
return;
}
_value = value;
_seenValue = true;
}
}
public override void OnCompleted()
{
if (!_seenValue)
{
try
{
throw new InvalidOperationException(Strings_Linq.NO_MATCHING_ELEMENTS);
}
catch (Exception e)
{
ForwardOnError(e);
}
}
else
{
ForwardOnNext(_value!);
ForwardOnCompleted();
}
}
}
}
}
}
View on GitHub (pinned to 94b5d5ab91)