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
- Ensure the stream emits exactly one value (use Take(1), FirstAsync, or .DistinctUntilChanged() if duplicates are identical).
- If multiple values are legitimate, use FirstAsync/LastAsync instead of SingleAsync.
- 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
- Use FirstAsync or Take(1) when multiple emissions are possible.
- Add DistinctUntilChanged when duplicates should be collapsed.
- Only use SingleAsync when exactly-one is a real invariant.
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
- NO_ELEMENTS
- Element no longer available in the buffer.
- MORE_THAN_ONE_MATCHING_ELEMENT
- Disposable already assigned.
- Value cannot be null. (Parameter 'func')
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)