{"record":{"id":"f3cc6d5c56f4c596","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-context-synchronization","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'context')","messagePattern":"Value cannot be null\\. \\(Parameter 'context'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs","lineNumber":106,"sourceCode":"        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <param name=\"source\">Source sequence.</param>\n        /// <param name=\"context\">Synchronization context to perform subscription and unsubscription actions on.</param>\n        /// <returns>The source sequence whose subscriptions and unsubscriptions happen on the specified synchronization context.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"context\"/> is <c>null</c>.</exception>\n        /// <remarks>\n        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified synchronization context.\n        /// In order to invoke observer callbacks on the specified synchronization context, e.g. to post callbacks to a UI thread represented by the synchronization context, use <see cref=\"Synchronization.ObserveOn{TSource}(IObservable{TSource}, SynchronizationContext)\"/>.\n        /// </remarks>\n        public static IObservable<TSource> SubscribeOn<TSource>(IObservable<TSource> source, SynchronizationContext context)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (context == null)\n            {\n                throw new ArgumentNullException(nameof(context));\n            }\n\n            return new SubscribeOnCtxObservable<TSource>(source, context);\n        }\n\n        private sealed class SubscribeOnCtxObservable<TSource> : ObservableBase<TSource>\n        {\n            private sealed class Subscription : IDisposable\n            {\n                private readonly IObservable<TSource> _source;\n                private readonly IObserver<TSource> _observer;\n                private readonly SynchronizationContext _context;\n                private SingleAssignmentDisposableValue _cancel;\n\n                public Subscription(IObservable<TSource> source, SynchronizationContext context, IObserver<TSource> observer)\n                {\n                    _source = source;\n                    _context = context;","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs#L88-L124","documentation":"ArgumentNullException thrown by Synchronization.SubscribeOn<TSource>(IObservable<TSource>, SynchronizationContext) when the SynchronizationContext argument is null. The context is what the subscription call is posted through; a null context cannot route the subscription, so it is rejected up front.","triggerScenarios":"Calling source.SubscribeOn(context) where the SynchronizationContext is null — most often SynchronizationContext.Current captured on a background thread where it is null, or a stored context field never initialized.","commonSituations":"Capturing the UI context on a worker thread instead of the UI thread; console apps and unit tests where no SynchronizationContext exists; async continuations that moved off the UI thread before the context was captured.","solutions":["Capture the context while on the UI thread (e.g. SynchronizationContext.Current inside a UI constructor or OnLoaded) and pass that captured instance.","Fall back to a scheduler-based overload such as source.SubscribeOn(Scheduler.Default) when no context is available.","Guard with a null check: if context == null, use an alternative subscription path or Scheduler.Immediate.","In tests or console apps, install a context (e.g. new SynchronizationContext()) or avoid the context overload entirely."],"exampleFix":"// before\nvar ctx = SynchronizationContext.Current; // null on background thread\nvar scheduled = source.SubscribeOn(ctx);\n// after\nvar ctx = SynchronizationContext.Current ?? new SynchronizationContext();\nvar scheduled = source.SubscribeOn(ctx);","handlingStrategy":"validation","validationCode":"var ctx = context ?? SynchronizationContext.Current ?? new SynchronizationContext();\nvar scheduled = source.SubscribeOn(ctx);","typeGuard":"bool IsUsableContext(SynchronizationContext context) => context is not null;","tryCatchPattern":"try\n{\n    var scheduled = source.SubscribeOn(ctx);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"context\")\n{\n    var scheduled = source.SubscribeOn(Scheduler.Immediate);\n}","preventionTips":["Capture SynchronizationContext.Current on the UI thread and store it; never assume it is non-null off-thread.","In console apps and tests, install a context or use scheduler-based overloads.","Null-coalesce with new SynchronizationContext() as a last-resort fallback.","Prefer source.SubscribeOn(Scheduler.Default) when thread affinity is not actually required."],"tags":["csharp","dotnet","null-argument","rx","synchronizationcontext"],"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"}