{"record":{"id":"f11b32f9d6a2966e","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-observer-max","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'observer')","messagePattern":"Value cannot be null\\. \\(Parameter 'observer'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Max.cs","lineNumber":39,"sourceCode":"        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            return CreateAsyncObservable<TSource>.From(\n                source,\n                comparer,\n                static (source, comparer, observer) => source.SubscribeSafeAsync(AsyncObserver.Max(observer, comparer)));\n        }\n    }\n\n    public partial class AsyncObserver\n    {\n        public static IAsyncObserver<TSource> Max<TSource>(IAsyncObserver<TSource> observer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n\n            return Max(observer, Comparer<TSource>.Default);\n        }\n\n        public static IAsyncObserver<TSource> Max<TSource>(IAsyncObserver<TSource> observer, IComparer<TSource> comparer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            var max = default(TSource);\n            var found = false;\n\n            return Create<TSource>(\n                async x =>\n                {\n                    if (found)","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Max.cs#L21-L57","documentation":"AsyncObserver.Max<TSource>(IAsyncObserver<TSource>) throws ArgumentNullException('observer') when the downstream observer is null. This factory builds the observer-side Max logic and delegates to Max(observer, Comparer<T>.Default); a null destination observer would have nowhere to emit the result, so it is rejected immediately.","triggerScenarios":"Calling AsyncObserver.Max(null) — commonly when hand-writing an operator and forwarding an observer parameter that is itself null, or when a custom IAsyncObservable.SubscribeAsync implementation passes null through.","commonSituations":"Custom operator authoring where the Create/subscription plumbing drops the observer; test harnesses that pass null observers; observer factories (e.g. from another operator) returning null on error paths.","solutions":["Pass a real downstream observer, e.g. from AsyncObserver.Create<T>(onNextAsync, onErrorAsync, onCompletedAsync).","In custom operators, validate the observer before forwarding it into AsyncObserver.Max.","If you want a no-op destination, use a terminal observer (e.g. a TaskCompletionSource-backed observer) instead of null."],"exampleFix":"// before\nvar maxObserver = AsyncObserver.Max(observer); // observer null\n\n// after\nvar downstream = AsyncObserver.Create<int>(\n    x => default(ValueTask),\n    err => default(ValueTask),\n    () => default(ValueTask));\nvar maxObserver = AsyncObserver.Max(downstream);","handlingStrategy":"validation","validationCode":"if (observer is null) throw new InvalidOperationException(\"Max requires a downstream observer\");","typeGuard":"static bool HasObserver<TSource>(IAsyncObserver<TSource>? o) => o is not null;","tryCatchPattern":"try { var maxObs = AsyncObserver.Max(observer); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"observer\") { /* build a terminal observer and retry */ }","preventionTips":["In custom operators, always forward the incoming observer parameter, never a nullable copy","Create test observers with AsyncObserver.Create<T> instead of stubbing null","Add Debug.Assert(observer != null) in operator plumbing during development"],"tags":["dotnet","null-argument","asyncrx","observer"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}