{"record":{"id":"926cd0a95f4aaff0","repo":"dotnet/reactive","slug":"source-dematerialize","errorCode":null,"errorMessage":"source","messagePattern":"source","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Dematerialize.cs","lineNumber":12,"sourceCode":"﻿// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT License.\n// See the LICENSE file in the project root for more information. \n\nnamespace 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        }","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Dematerialize.cs#L1-L30","documentation":"Dematerialize throws ArgumentNullException when the source IAsyncObservable<Notification<TSource>> is null. The operator converts materialized notifications back into regular OnNext/OnError/OnCompleted signals and validates its source eagerly. A null source is a composition-time programming error.","triggerScenarios":"Calling AsyncObservable.Dematerialize(null) or chaining it on a null result of another call.","commonSituations":"A pipeline stage that materializes notifications returning null on an error path; unit tests constructing the observable lazily and forgetting to assign it.","solutions":["Pass a valid observable of Notification<TSource> (typically the result of Materialize).","Null-check or coalesce the source before applying Dematerialize.","Fix the upstream producer so it returns an empty/failed observable instead of null."],"exampleFix":"// before\nvar dematerialized = AsyncObservable.Dematerialize(materialized); // materialized == null\n// after\nif (materialized == null) throw new InvalidOperationException(\"materialize stage produced no observable\");\nvar dematerialized = AsyncObservable.Dematerialize(materialized);","handlingStrategy":"validation","validationCode":"if (materialized is null) throw new InvalidOperationException(\"materialized source required\");\nvar dematerialized = AsyncObservable.Dematerialize(materialized);","typeGuard":"bool IsValidSource<T>(IAsyncObservable<Notification<T>>? s) => s is not null;","tryCatchPattern":"try\n{\n    var dematerialized = AsyncObservable.Dematerialize(materialized);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"source\")\n{\n    logger.LogError(ex, \"Dematerialize called with null source\");\n    throw;\n}","preventionTips":["Pair Dematerialize only with results of Materialize in the same pipeline.","Make observable-producing methods non-nullable by contract.","Run unit tests that exercise the full materialize/dematerialize round trip."],"tags":["argument-null","async-rx","operators","fail-fast"],"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"}