{"record":{"id":"a0d0c52351a66ead","repo":"dotnet/reactive","slug":"more-than-one-matching-element-singleordefaultasync","errorCode":null,"errorMessage":"MORE_THAN_ONE_MATCHING_ELEMENT","messagePattern":"MORE_THAN_ONE_MATCHING_ELEMENT","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs","lineNumber":106,"sourceCode":"                    var b = false;\n\n                    try\n                    {\n                        b = _predicate(value);\n                    }\n                    catch (Exception ex)\n                    {\n                        ForwardOnError(ex);\n                        return;\n                    }\n\n                    if (b)\n                    {\n                        if (_seenValue)\n                        {\n                            try\n                            {\n                                throw new InvalidOperationException(Strings_Linq.MORE_THAN_ONE_MATCHING_ELEMENT);\n                            }\n                            catch (Exception e)\n                            {\n                                ForwardOnError(e);\n                            }\n                            return;\n                        }\n\n                        _value = value;\n                        _seenValue = true;\n                    }\n                }\n\n                public override void OnCompleted()\n                {\n                    ForwardOnNext(_value);\n                    ForwardOnCompleted();\n                }","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable/SingleOrDefaultAsync.cs#L88-L124","documentation":"The predicate-based overload of SingleOrDefaultAsync throws InvalidOperationException(MORE_THAN_ONE_MATCHING_ELEMENT) in OnNext when a second element passes the predicate after one already matched. The operator asserts that at most one element of the source satisfies the filter; any additional match is a contract violation surfaced via OnError.","triggerScenarios":"Calling Observable.SingleOrDefaultAsync(source, predicate) where two or more source elements satisfy the predicate. Raised in the OnNext path at SingleOrDefaultAsync.cs:106 after evaluating the predicate to true while _seenValue is already true.","commonSituations":"Filtering by a key assumed unique (e.g. x => x.Id == targetId) against data containing duplicates after a merge/import; predicates that are looser than intended (matching multiple rows in a DB-backed stream); schema changes that break a uniqueness assumption.","solutions":["Tighten the predicate so it matches exactly one element (filter on a true unique key).","Use .Where(predicate).Take(1) plus FirstOrDefaultAsync when multiple matches are legal and any one suffices.","Deduplicate the source first (Distinct/DistinctBy semantics via GroupBy+SelectMany) before applying the operator.","Catch the InvalidOperationException and decide how to handle genuinely duplicated matches."],"exampleFix":"// before\nvar user = await users.SingleOrDefaultAsync(u => u.Email == email); // throws on duplicate emails\n\n// after\nvar user = await users.Where(u => u.Email == email).Take(1).LastOrDefaultAsync();\n// or enforce uniqueness upstream on the email column","handlingStrategy":"validation","validationCode":"// Verify predicate uniqueness against the data before relying on the operator:\nint matches = await source.Where(predicate).Count();\nif (matches > 1) { /* resolve duplicates (tighten key, deduplicate) first */ }","typeGuard":"static bool MatchesAtMostOne<T>(IList<T> items, Func<T, bool> predicate) => items.Count(predicate) <= 1;","tryCatchPattern":"source.SingleOrDefaultAsync(predicate).Subscribe(\n    value => { /* use value or default */ },\n    ex => { if (ex is InvalidOperationException) { /* multiple matches: log and choose first */ } else throw ex; });","preventionTips":["Filter on genuinely unique keys (IDs), not on fuzzy fields like names or emails unless uniqueness is enforced upstream.","Prefer .Where(predicate).Take(1).LastOrDefaultAsync() when any single match suffices.","Deduplicate source data (DB unique constraints, Distinct) before it reaches the stream.","Add tests with duplicate-match data for every predicate-based SingleOrDefault call site."],"tags":["rx","reactive-extensions","singleordefault-operator","predicate-filter","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"}