{"record":{"id":"c42cfc5a44ab129c","repo":"dotnet/reactive","slug":"throw-new-argumentnullexception-nameof-observer-scan","errorCode":null,"errorMessage":"throw new ArgumentNullException(nameof(observer));","messagePattern":"throw new ArgumentNullException\\(nameof\\(observer\\)\\);","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Scan.cs","lineNumber":69,"sourceCode":"        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (func == null)\n                throw new ArgumentNullException(nameof(func));\n\n            return CreateAsyncObservable<TResult>.From(\n                source,\n                (func, seed),\n                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.Scan(observer, state.seed, state.func)));\n        }\n    }\n\n    public partial class AsyncObserver\n    {\n        public static IAsyncObserver<TSource> Scan<TSource>(IAsyncObserver<TSource> observer, Func<TSource, TSource, TSource> func)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n            if (func == null)\n                throw new ArgumentNullException(nameof(func));\n\n            var hasValue = false;\n            var value = default(TSource);\n\n            return Create<TSource>(\n                async x =>\n                {\n                    if (hasValue)\n                    {\n                        try\n                        {\n                            value = func(value, x);\n                        }\n                        catch (Exception ex)\n                        {\n                            await observer.OnErrorAsync(ex).ConfigureAwait(false);","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Scan.cs#L51-L87","documentation":"AsyncObserver.Scan<TSource>(observer, func) — the internal observer factory used by the unseeded sync Scan operator — throws ArgumentNullException because the downstream observer was null. This guard protects the observer-wrapping layer; in typical use the public Scan method always supplies a real observer, so hitting this means Scan was invoked through internal APIs with a broken observer.","triggerScenarios":"Calling AsyncObserver.Scan(null, func) directly or via a custom operator that forwards a null IAsyncObserver<TSource> — e.g. a hand-rolled SubscribeSafeAsync path that drops the observer on error.","commonSituations":"Custom operator/observer implementations reusing AsyncObserver.Scan with an observer that was never constructed; testing internal APIs; observer lost through a nullable pipeline field.","solutions":["Pass the actual downstream observer: AsyncObserver.Scan(downstream, func).","Fix the custom subscription path so the observer is created before Scan is called.","Prefer the public source.Scan(func) API, which wires the observer for you."],"exampleFix":"// before\nIAsyncObserver<int> downstream = null;\nvar obs = AsyncObserver.Scan(downstream, (a, b) => a + b); // throws\n\n// after\nvar obs = AsyncObserver.Scan(observer, (a, b) => a + b); // observer from the subscription callback","handlingStrategy":"validation","validationCode":"if (observer is null) throw new InvalidOperationException(\"downstream observer must be provided to AsyncObserver.Scan\");\nvar obs = AsyncObserver.Scan(observer, func);","typeGuard":"static bool HasObserver<TSource>(IAsyncObserver<TSource>? o) => o is not null;","tryCatchPattern":"try { var obs = AsyncObserver.Scan(observer, f); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"observer\") { log.LogError(\"observer chain broken\"); throw; }","preventionTips":["Prefer the public source.Scan(func) operator over manual AsyncObserver wiring.","In custom operators, construct the observer before calling factory methods.","Keep observer fields non-nullable in subscription implementations."],"tags":["argument-null","observer","async-reactive","internal-api"],"backgroundTag":"null-argument","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"}