{"record":{"id":"184bfaaa53c97c17","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-context-observer-extensions","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'context')","messagePattern":"Value cannot be null\\. \\(Parameter 'context'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Observer.Extensions.cs","lineNumber":327,"sourceCode":"\n        /// <summary>\n        /// Schedules the invocation of observer methods on the given synchronization context.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the elements received by the source observer.</typeparam>\n        /// <param name=\"observer\">The observer to schedule messages for.</param>\n        /// <param name=\"context\">Synchronization context to schedule observer messages on.</param>\n        /// <returns>Observer whose messages are scheduled on the given synchronization context.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"observer\"/> or <paramref name=\"context\"/> is null.</exception>\n        public static IObserver<T> NotifyOn<T>(this IObserver<T> observer, SynchronizationContext context)\n        {\n            if (observer == null)\n            {\n                throw new ArgumentNullException(nameof(observer));\n            }\n\n            if (context == null)\n            {\n                throw new ArgumentNullException(nameof(context));\n            }\n\n            return new ObserveOnObserver<T>(new SynchronizationContextScheduler(context), observer);\n        }\n\n        /// <summary>\n        /// Converts an observer to a progress object.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the progress objects received by the source observer.</typeparam>\n        /// <param name=\"observer\">The observer to convert.</param>\n        /// <returns>Progress object whose Report messages correspond to the observer's OnNext messages.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"observer\"/> is null.</exception>\n        public static IProgress<T> ToProgress<T>(this IObserver<T> observer)\n        {\n            if (observer == null)\n            {\n                throw new ArgumentNullException(nameof(observer));\n            }","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Observer.Extensions.cs#L309-L345","documentation":"NotifyOn<T>(IObserver<T>, SynchronizationContext) throws ArgumentNullException when the context parameter is null. The SynchronizationContext is used to build a SynchronizationContextScheduler that marshals callbacks (commonly to the UI thread), so it must be provided.","triggerScenarios":"Calling observer.NotifyOn(null) — e.g. SynchronizationContext.Current is null (no UI thread context captured), or a context field never assigned.","commonSituations":"Calling SynchronizationContext.Current from a background/thread-pool thread where it is null; capturing the context too late (after the UI thread's message loop setup); unit tests without a synchronization context installed.","solutions":["Capture the context on the UI thread first: var ctx = SynchronizationContext.Current; then pass it","Use the IScheduler overload with an appropriate scheduler (e.g. DispatcherScheduler.Current for WPF) when no SynchronizationContext exists","Post subscription setup to the UI thread so SynchronizationContext.Current is populated before NotifyOn is called","Fallback: observer.NotifyOn(Scheduler.Default) if UI marshaling is not required"],"exampleFix":"// before\nvar notified = observer.NotifyOn(SynchronizationContext.Current); // null on background thread\n// after\n// on the UI thread:\n_uiContext = SynchronizationContext.Current;\n// ...\nvar notified = observer.NotifyOn(_uiContext ?? new SynchronizationContextScheduler(SynchronizationContext.Current ?? new SynchronizationContext()));","handlingStrategy":"validation","validationCode":"var ctx = SynchronizationContext.Current ?? throw new InvalidOperationException(\"No SynchronizationContext; call from the UI thread.\");\nvar notified = observer.NotifyOn(ctx);","typeGuard":"static bool HasSyncContext(SynchronizationContext? c) => c is not null;","tryCatchPattern":"try { var notified = observer.NotifyOn(context); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"context\")\n{\n    var notified = observer.NotifyOn(Scheduler.Default); // fallback, no UI marshaling\n}","preventionTips":["Capture SynchronizationContext.Current on the UI thread and store it","Never assume SynchronizationContext.Current is non-null on thread-pool threads","Use DispatcherScheduler (WPF) or Control.BeginInvoke (WinForms) alternatives when no context exists","Capture the context before starting background work"],"tags":["null-argument","dotnet","rx","synchronization-context","ui-threading"],"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"}