{"record":{"id":"6d603b5c173a6086","repo":"dotnet/reactive","slug":"more-than-one-element-singleordefaultasync","errorCode":null,"errorMessage":"MORE_THAN_ONE_ELEMENT","messagePattern":"MORE_THAN_ONE_ELEMENT","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs","lineNumber":38,"sourceCode":"            protected override void Run(_ sink) => sink.Run(_source);\n\n            internal sealed class _ : Sink<TSource, TSource?>\n            {\n                private TSource? _value;\n                private bool _seenValue;\n\n                public _(IObserver<TSource?> observer)\n                    : base(observer)\n                {\n                }\n\n                public override void OnNext(TSource value)\n                {\n                    if (_seenValue)\n                    {\n                        try\n                        {\n                            throw new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_ELEMENT);\n                        }\n                        catch (Exception e)\n                        {\n                            ForwardOnError(e);\n                        }\n                        return;\n                    }\n\n                    _value = value;\n                    _seenValue = true;\n                }\n\n                public override void OnCompleted()\n                {\n                    ForwardOnNext(_value);\n                    ForwardOnCompleted();\n                }\n            }","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs#L20-L56","documentation":"SingleOrDefaultAsync throws InvalidOperationException(MORE_THAN_ONE_ELEMENT) from OnNext when a second element arrives after one was already observed. 'OrDefault' only relaxes the empty case, not the uniqueness requirement: the sequence must contain at most one element. The error is forwarded via OnError as soon as the duplicate value is seen, cancelling further processing.","triggerScenarios":"Calling Observable.SingleOrDefaultAsync(source) on a hot or cold observable that emits two or more OnNext values. Raised in the observer's OnNext override at SingleOrDefaultAsync.cs:38 when _seenValue is already true.","commonSituations":"Assuming SingleOrDefault behaves like ElementAt(0)/First with a fallback; streams that legitimately emit multiple updates (e.g. repeated config pushes, retries emitting duplicates); replacing First with SingleOrDefault without checking cardinality guarantees.","solutions":["Use Take(1) (or FirstOrDefaultAsync) if only the first element is needed and duplicates are expected.","Use .DistinctUntilChanged() before SingleOrDefaultAsync if duplicate values should be collapsed.","If the source is truly required to be unique, fix the producer so it never emits more than one value.","Catch InvalidOperationException from the subscription and fall back to the default or last-known value."],"exampleFix":"// before\nvar value = await updates.SingleOrDefaultAsync(); // throws if 2+ updates arrive\n\n// after\nvar value = await updates.Take(1).LastOrDefaultAsync(); // first update, no throw\n// or if uniqueness is contractual:\nvar value = await updates.DistinctUntilChanged().SingleOrDefaultAsync();","handlingStrategy":"validation","validationCode":"// Enforce single-emission at the producer, or buffer and check count:\nvar buffered = await source.ToList();\nif (buffered.Count > 1) { /* handle duplicates before calling SingleOrDefaultAsync */ }","typeGuard":"static bool HasAtMostOne<T>(IList<T> buffered) => buffered.Count <= 1;","tryCatchPattern":"source.SingleOrDefaultAsync().Subscribe(\n    value => { /* use value or default */ },\n    ex => { if (ex is InvalidOperationException) { /* duplicate element path: fall back to First */ } else throw ex; });","preventionTips":["Remember OrDefault only covers the empty case, not duplicates.","Use Take(1)/FirstOrDefaultAsync when cardinality is not guaranteed.","Add .DistinctUntilChanged() when duplicate notifications are expected from hot sources.","Model 'at most one' semantics at the producer with a Replay(1)/BehaviorSubject rather than hoping downstream."],"tags":["rx","reactive-extensions","singleordefault-operator","duplicate-elements"],"backgroundTag":"more-than-one-element","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}