{"record":{"id":"68a8012607df2940","repo":"dotnet/reactive","slug":"observer-dematerialize","errorCode":null,"errorMessage":"observer","messagePattern":"observer","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Dematerialize.cs","lineNumber":23,"sourceCode":"namespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TSource> Dematerialize<TSource>(this IAsyncObservable<Notification<TSource>> source)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n\n            return Create<Notification<TSource>, TSource>(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.Dematerialize(observer)));\n        }\n    }\n\n    public partial class AsyncObserver\n    {\n        public static IAsyncObserver<Notification<TSource>> Dematerialize<TSource>(IAsyncObserver<TSource> observer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n\n            return Create<Notification<TSource>>(\n                n => n.AcceptAsync(observer),\n                observer.OnErrorAsync,\n                observer.OnCompletedAsync\n            );\n        }\n    }\n}\n","sourceCodeStart":5,"sourceCodeEnd":33,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Dematerialize.cs#L5-L33","documentation":"AsyncObserver.Dematerialize throws ArgumentNullException when the downstream IAsyncObserver<TSource> is null. The observer receives the dematerialized notifications, so it is required and validated immediately. This overload is used when writing custom operators, so nulls typically come from hand-rolled subscription plumbing.","triggerScenarios":"Calling AsyncObserver.Dematerialize<TSource>(null) inside a custom operator's subscribe path, or forwarding a null observer variable.","commonSituations":"Custom Create(...) lambdas where the observer parameter is mistakenly null; composing observers where an earlier stage returned null on a factory failure.","solutions":["Pass the actual downstream observer from your operator's subscribe delegate.","Validate your own factory inputs before constructing the Dematerialize observer.","Use the built-in Create(source, observer) operator overload instead of manually wiring observers."],"exampleFix":"// before\nreturn source.SubscribeSafeAsync(AsyncObserver.Dematerialize(observer)); // observer null\n// after\nif (observer == null) throw new ArgumentNullException(nameof(observer));\nreturn source.SubscribeSafeAsync(AsyncObserver.Dematerialize(observer));","handlingStrategy":"validation","validationCode":"if (observer is null) throw new ArgumentNullException(nameof(observer));\nvar dematerializeObserver = AsyncObserver.Dematerialize(observer);","typeGuard":"bool HasDownstream<T>(IAsyncObserver<T>? o) => o is not null;","tryCatchPattern":"try\n{\n    var o = AsyncObserver.Dematerialize(observer);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"observer\")\n{\n    logger.LogError(ex, \"Custom operator passed null observer to Dematerialize\");\n    throw;\n}","preventionTips":["In custom operators, always forward the observer parameter you received from Create.","Guard custom operator entry points with ArgumentNullException checks.","Add unit tests for custom operators that assert null-argument behavior."],"tags":["argument-null","async-rx","observer","custom-operators"],"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"}