{"record":{"id":"4e0e9ef6f78337c6","repo":"dotnet/reactive","slug":"strings-linq-no-elements-max","errorCode":null,"errorMessage":"Strings_Linq.NO_ELEMENTS","messagePattern":"Strings_Linq\\.NO_ELEMENTS","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs","lineNumber":78,"sourceCode":"                    if (comparison > 0)\n                    {\n                        _lastValue = value;\n                    }\n                }\n                else\n                {\n                    _hasValue = true;\n                    _lastValue = value;\n                }\n            }\n\n            public override void OnCompleted()\n            {\n                if (!_hasValue)\n                {\n                    try\n                    {\n                        throw new InvalidOperationException(Strings_Linq.NO_ELEMENTS);\n                    }\n                    catch (Exception e)\n                    {\n                        ForwardOnError(e);\n                    }\n                }\n                else\n                {\n                    ForwardOnNext(_lastValue!);\n                    ForwardOnCompleted();\n                }\n            }\n        }\n\n        private sealed class Null : _\n        {\n            private TSource? _lastValue;\n","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable/Max.cs#L60-L96","documentation":"The Rx Max operator tracks whether the source sequence produced any element. When the observer's OnCompleted fires and no value was ever seen, the operator cannot produce a maximum, so it throws System.InvalidOperationException with the message Strings_Linq.NO_ELEMENTS (\"Sequence contains no elements\"). This mirrors the synchronous LINQ-to-Objects behavior of Enumerable.Max on an empty sequence: an aggregate over zero items is undefined rather than null.","triggerScenarios":"Subscribing to Observable.Max over a source that completes without emitting any element — e.g. Observable.Empty<int>().Max(), a Where/filter that excludes every item, or an observable that completes immediately — and the anonymous observer in Max.cs (line ~78) reaches OnCompleted with _hasValue == false.","commonSituations":"Filtering a stream with a predicate that matches nothing (e.g. temperatures.Where(t => t > 100).Max()); querying a data feed that returns an empty batch; time-windowed aggregations where no events arrived during the window; race where the source completes before the first value due to cancellation or a hot sequence already finished.","solutions":["Ensure the source can emit at least one value, or validate emptiness before aggregating.","Use MaxOrDefault-style behavior by prepending a default: source.DefaultIfEmpty(0).Max().","Use Observable.Empty detection first, e.g. Any(): await source.Any() before calling Max, or branch on it.","For nullable-friendly semantics, aggregate with Scan + LastOrDefaultAsync or use System.Linq.AsyncEnumerable MaxAsync which throws only per its own contract.","If the empty case is expected, catch InvalidOperationException around the subscription and supply a fallback value."],"exampleFix":"// before\nvar max = await temperatures.Max(); // throws if temperatures is empty\n\n// after\nvar max = await temperatures\n    .DefaultIfEmpty(double.NaN)\n    .Max(); // NaN sentinel instead of InvalidOperationException","handlingStrategy":"validation","validationCode":"bool hasAny = await source.Any();\nif (!hasAny) return defaultValue; // avoids InvalidOperationException from Max\nvar max = await source.Max();","typeGuard":"static async Task<bool> IsEmptyAsync<T>(this IObservable<T> source) =>\n    !await source.Any();","tryCatchPattern":"try\n{\n    var max = await source.Max();\n    return max;\n}\ncatch (InvalidOperationException ex) when (ex.Message == Strings_Linq.NO_ELEMENTS)\n{\n    return defaultValue;\n}","preventionTips":["Prefer DefaultIfEmpty(...) before Max/Min whenever the source may legitimately be empty.","Check Any()/IsEmpty before aggregating in query pipelines.","In tests, never Complete a Subject before publishing at least one value if Min/Max subscribe to it.","Keep empty-window handling explicit in windowed/grouped aggregations."],"tags":["reactive","linq","empty-sequence","aggregation","system-reactive"],"backgroundTag":"empty-result-set","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"}