dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'continuation')
Error message
Value cannot be null. (Parameter 'continuation')
What it means
SchedulerOperation implements the awaitable pattern for scheduler operations; OnCompleted registers the continuation passed by the compiler-generated awaiter. It throws ArgumentNullException when continuation is null. The compiler normally always passes a valid continuation, so this typically indicates manual/incorrect awaiter usage.
Solutions
- Always pass a non-null Action continuation to OnCompleted
- Await the SchedulerOperation with normal await syntax instead of calling OnCompleted manually
- Fix custom awaiter code to forward the real continuation
Example fix
// before
operation.OnCompleted(null);
// after
operation.OnCompleted(() => Console.WriteLine("resumed"));
// or simply:
await operation; Defensive patterns
Strategy: validation
Validate before calling
if (continuation != null) operation.OnCompleted(continuation);
Type guard
static bool CanRegister(Action c) => c != null;
Try / catch
try { operation.OnCompleted(continuation); }
catch (ArgumentNullException) { /* supply a real continuation or skip */ } Prevention
- Prefer await over manual OnCompleted calls
- In custom awaiters, always forward the compiler-provided continuation
- Never invoke awaiter plumbing with null delegates in tests
When it happens
Trigger: Calling operation.OnCompleted(null) directly; implementing a custom awaiter that passes a null continuation; misuse of the awaitable from another language or generated code.
Common situations: Hand-rolled awaiter implementations; reflection-based code invoking OnCompleted; tests exercising the awaitable pattern manually.
Related errors
- action (Parameter 'action')
- action (Parameter 'action')
- action (Parameter 'action')
- action (Parameter 'action')
- action (Parameter 'action')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/7ec3842cdd618021.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Concurrency/SchedulerOperation.cs:93
/// <summary>
/// Indicates whether the scheduler operation has completed. Returns false unless cancellation was already requested.
/// </summary>
public bool IsCompleted => _cancellationToken.IsCancellationRequested;
/// <summary>
/// Completes the scheduler operation, throwing an OperationCanceledException in case cancellation was requested.
/// </summary>
public void GetResult() => _cancellationToken.ThrowIfCancellationRequested();
/// <summary>
/// Registers the continuation with the scheduler operation.
/// </summary>
/// <param name="continuation">Continuation to be run on the originating scheduler.</param>
public void OnCompleted(Action continuation)
{
if (continuation == null)
{
throw new ArgumentNullException(nameof(continuation));
}
if (_continuation != null)
{
throw new InvalidOperationException(Strings_Core.SCHEDULER_OPERATION_ALREADY_AWAITED);
}
if (_postBackToOriginalContext)
{
var ctx = SynchronizationContext.Current;
if (ctx != null)
{
var original = continuation;
continuation = () =>
{
//
// No need for OperationStarted and OperationCompleted calls here;
// this code is invoked through await support and will have a wayView on GitHub (pinned to 94b5d5ab91)