{"record":{"id":"cb63519feef58e13","repo":"dotnet/reactive","slug":"throw-new-argumentnullexception-nameof-observer-sample","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/Sample.cs","lineNumber":79,"sourceCode":"                source,\n                (scheduler, interval),\n                static async (source, state, observer) =>\n                {\n                    var (sourceSink, sampler) = await AsyncObserver.Sample(observer, state.interval, state.scheduler).ConfigureAwait(false);\n\n                    var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false);\n\n                    return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler);\n                });\n        }\n    }\n\n    public partial class AsyncObserver\n    {\n        public static (IAsyncObserver<TSource>, IAsyncObserver<TSample>) Sample<TSource, TSample>(IAsyncObserver<TSource> observer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n\n            var gate = new AsyncGate();\n\n            var hasValue = false;\n            var value = default(TSource);\n            var atEnd = false;\n\n            async ValueTask OnSampleAsync()\n            {\n                using (await gate.LockAsync().ConfigureAwait(false))\n                {\n                    if (hasValue)\n                    {\n                        hasValue = false;\n                        await observer.OnNextAsync(value).ConfigureAwait(false);\n                    }\n\n                    if (atEnd)","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Sample.cs#L61-L97","documentation":"The AsyncObserver.Sample<TSource,TSample>(observer) sink factory throws ArgumentNullException when the observer is null. This lower-level API builds the paired (source observer, sampler observer) sink used by the operator, and it validates the downstream observer before allocating the gate and state.","triggerScenarios":"Calling AsyncObserver.Sample<T,TSample>(null) directly — e.g. hand-rolling the Sample operator internals, or forwarding a null downstream observer from a custom operator pipeline.","commonSituations":"Custom operator authorship where the observer comes from an outer subscription that can be null; wiring observer pairs in test harnesses; refactoring that lost the downstream observer argument.","solutions":["Pass a real downstream IAsyncObserver (e.g. one obtained from AsyncObserver.Create or your sink chain)","Guard in the calling operator: if (observer == null) throw new ArgumentNullException(nameof(observer)) before delegating","Ensure the custom operator forwards its own observer parameter, not a field that may be null","Subscribe via the public Sample operator instead of constructing the sink manually"],"exampleFix":"// before\nvar (src, smp) = AsyncObserver.Sample<Price, Tick>(downstream); // downstream may be null\n// after\nif (downstream == null) throw new ArgumentNullException(nameof(downstream));\nvar (src, smp) = AsyncObserver.Sample<Price, Tick>(downstream);","handlingStrategy":"validation","validationCode":"if (observer is null) throw new ArgumentNullException(nameof(observer));\nvar (srcObs, smpObs) = AsyncObserver.Sample<TSource, TSample>(observer);","typeGuard":"static bool HasObserver<TSource>(IAsyncObserver<TSource>? o) => o is not null;","tryCatchPattern":"try\n{\n    var (srcObs, smpObs) = AsyncObserver.Sample<TSource, TSample>(observer);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"observer\")\n{\n    // downstream was not wired; fix subscription chain\n    throw new InvalidOperationException(\"Sample sink requires a downstream observer\", ex);\n}","preventionTips":["Forward the observer parameter, never a possibly-null field, when writing custom operators","Null-check downstream observers at operator entry","Prefer the public AsyncObservable.Sample operator over raw sink APIs","Initialize observer fields in constructors, not lazily"],"tags":["csharp","null-argument","observer","async-reactive"],"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"}