dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'context')
Error message
Value cannot be null. (Parameter 'context')
What it means
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.
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.
Example fix
// before var ctx = SynchronizationContext.Current; // null on background thread var scheduled = source.SubscribeOn(ctx); // after var ctx = SynchronizationContext.Current ?? new SynchronizationContext(); var scheduled = source.SubscribeOn(ctx);
Defensive patterns
Strategy: validation
Validate before calling
var ctx = context ?? SynchronizationContext.Current ?? new SynchronizationContext(); var scheduled = source.SubscribeOn(ctx);
Type guard
bool IsUsableContext(SynchronizationContext context) => context is not null;
Try / catch
try
{
var scheduled = source.SubscribeOn(ctx);
}
catch (ArgumentNullException ex) when (ex.ParamName == "context")
{
var scheduled = source.SubscribeOn(Scheduler.Immediate);
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Value cannot be null. (Parameter 'action')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'scheduler')
- observer
- scheduler (Value cannot be null)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/f3cc6d5c56f4c596.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs:106
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <param name="source">Source sequence.</param>
/// <param name="context">Synchronization context to perform subscription and unsubscription actions on.</param>
/// <returns>The source sequence whose subscriptions and unsubscriptions happen on the specified synchronization context.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="context"/> is <c>null</c>.</exception>
/// <remarks>
/// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified synchronization context.
/// 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)"/>.
/// </remarks>
public static IObservable<TSource> SubscribeOn<TSource>(IObservable<TSource> source, SynchronizationContext context)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return new SubscribeOnCtxObservable<TSource>(source, context);
}
private sealed class SubscribeOnCtxObservable<TSource> : ObservableBase<TSource>
{
private sealed class Subscription : IDisposable
{
private readonly IObservable<TSource> _source;
private readonly IObserver<TSource> _observer;
private readonly SynchronizationContext _context;
private SingleAssignmentDisposableValue _cancel;
public Subscription(IObservable<TSource> source, SynchronizationContext context, IObserver<TSource> observer)
{
_source = source;
_context = context;View on GitHub (pinned to 94b5d5ab91)