dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'asyncLock')
Error message
Value cannot be null. (Parameter 'asyncLock')
What it means
Observer.Synchronize<T>(IObserver<T>, AsyncLock) throws ArgumentNullException when the asyncLock parameter is null. The AsyncLock provides the mutual exclusion for notifications delivered to the observer; without it the wrapper cannot function, so Rx validates it upfront.
Solutions
- Create and pass an AsyncLock instance: new AsyncLock()
- Ensure the AsyncLock field is initialized before use (readonly field initialized inline)
- Do not null out the AsyncLock on dispose if it will be referenced again; keep a fresh instance per observer chain
- Verify you are targeting the correct overload (object gate vs AsyncLock) and supply the matching type
Example fix
// before AsyncLock gate = _lock; // null after dispose var synced = Observer.Synchronize(observer, gate); // after using var asyncLock = new AsyncLock(); var synced = Observer.Synchronize(observer, asyncLock);
Defensive patterns
Strategy: validation
Validate before calling
if (observer is null) throw new ArgumentNullException(nameof(observer)); if (asyncLock is null) asyncLock = new AsyncLock();
Type guard
static bool HasAsyncLock(AsyncLock? l) => l is not null;
Try / catch
try { var synced = Observer.Synchronize(observer, asyncLock); }
catch (ArgumentNullException ex) when (ex.ParamName == "asyncLock")
{
asyncLock = new AsyncLock();
var synced = Observer.Synchronize(observer, asyncLock);
} Prevention
- Initialize AsyncLock fields inline: private readonly AsyncLock _lock = new AsyncLock();
- Do not null the AsyncLock when disposing if it may be reused
- Create a fresh AsyncLock per observer chain rather than sharing nullable instances
- Track dispose lifecycle so a disposed lock is never passed again
When it happens
Trigger: Calling Observer.Synchronize(observer, null) — commonly when the AsyncLock is created lazily, disposed and nulled earlier, or accidentally passing null in place of a gate/lock object.
Common situations: AsyncLock disposed with the owning class and nulled, then reused; a factory method returning null; copy-paste between the object-gate and AsyncLock overloads.
Related errors
- predicate
- Value cannot be null. (Parameter 'source5')
- Value cannot be null. (Parameter 'gate')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'scheduler')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/43cef115fd7b1d2c.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Observer.Extensions.cs:281
/// <summary>
/// Synchronizes access to the observer such that its callback methods cannot be called concurrently, using the specified asynchronous lock to protect against concurrent and reentrant access.
/// This overload is useful when coordinating multiple observers that access shared state by synchronizing on a common asynchronous lock.
/// </summary>
/// <typeparam name="T">The type of the elements received by the source observer.</typeparam>
/// <param name="observer">The observer whose callbacks should be synchronized.</param>
/// <param name="asyncLock">Gate object to synchronize each observer call on.</param>
/// <returns>An observer that delivers callbacks to the specified observer in a synchronized manner.</returns>
/// <exception cref="ArgumentNullException"><paramref name="observer"/> or <paramref name="asyncLock"/> is null.</exception>
public static IObserver<T> Synchronize<T>(IObserver<T> observer, AsyncLock asyncLock)
{
if (observer == null)
{
throw new ArgumentNullException(nameof(observer));
}
if (asyncLock == null)
{
throw new ArgumentNullException(nameof(asyncLock));
}
return new AsyncLockObserver<T>(observer, asyncLock);
}
/// <summary>
/// Schedules the invocation of observer methods on the given scheduler.
/// </summary>
/// <typeparam name="T">The type of the elements received by the source observer.</typeparam>
/// <param name="observer">The observer to schedule messages for.</param>
/// <param name="scheduler">Scheduler to schedule observer messages on.</param>
/// <returns>Observer whose messages are scheduled on the given scheduler.</returns>
/// <exception cref="ArgumentNullException"><paramref name="observer"/> or <paramref name="scheduler"/> is null.</exception>
public static IObserver<T> NotifyOn<T>(this IObserver<T> observer, IScheduler scheduler)
{
if (observer == null)
{
throw new ArgumentNullException(nameof(observer));View on GitHub (pinned to 94b5d5ab91)