dotnet/reactive · error · ArgumentNullException
end
Error message
end
What it means
The single-argument FromAsyncPattern<TArg1,TResult> overload throws ArgumentNullException('end') when the end delegate Func<IAsyncResult, TResult> is null. Both begin and end delegates are mandatory: end converts the IAsyncResult into the final result and completes the observable sequence. Validation happens when the wrapper Func is created.
Solutions
- Supply the EndXxx method (or a lambda wrapping it) as the end delegate
- Null-check delegates obtained dynamically before passing them
- Use Observable.FromAsync with a Task-returning function instead of APM
Example fix
// before var f = Observable.FromAsyncPattern<int, byte[]>(begin, null); // after var f = Observable.FromAsyncPattern<int, byte[]>(begin, iar => stream.EndRead(iar));
Defensive patterns
Strategy: validation
Validate before calling
if (begin == null || end == null) throw new InvalidOperationException("Both begin and end delegates are required");
var f = Observable.FromAsyncPattern<TArg1, TResult>(begin, end); Type guard
static bool ValidApmPair<TArg1,TResult>(Func<TArg1, AsyncCallback, object?, IAsyncResult> b, Func<IAsyncResult, TResult> e) => b != null && e != null;
Try / catch
try
{
var f = Observable.FromAsyncPattern<TArg1, TResult>(begin, end);
}
catch (ArgumentNullException ex) when (ex.ParamName == "end")
{
// supply the end delegate
} Prevention
- Port Begin/End pairs as complete units
- Unit-test wrapper construction with real delegates
- Use Task-based APIs to eliminate APM wiring
When it happens
Trigger: Observable.FromAsyncPattern<TArg1,TResult>(begin, null) - the end argument omitted or resolved to null.
Common situations: Wrapping legacy Begin/End pairs where only the Begin call was ported; conditional wiring code that leaves end unassigned; wrong generic type inference pushing developers toward the wrong overload.
Related errors
- Value cannot be null. (Parameter 'end')
- begin
- Value cannot be null. (Parameter 'functionAsync')
- Value cannot be null. (Parameter 'options')
- Value cannot be null. (Parameter 'resourceFactoryAsync')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/f688722a55f18a66.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs:62
/// </summary>
/// <typeparam name="TArg1">The type of the first argument passed to the begin delegate.</typeparam>
/// <typeparam name="TResult">The type of the result returned by the end delegate.</typeparam>
/// <param name="begin">The delegate that begins the asynchronous operation.</param>
/// <param name="end">The delegate that ends the asynchronous operation.</param>
/// <returns>Function that can be used to start the asynchronous operation and retrieve the result as an observable sequence.</returns>
/// <exception cref="ArgumentNullException"><paramref name="begin"/> or <paramref name="end"/> is null.</exception>
/// <remarks>Each invocation of the resulting function will cause the asynchronous operation to be started. Subscription to the resulting sequence has no observable side-effect, and each subscription will produce the asynchronous operation's result.</remarks>
[Obsolete(Constants_Linq.UseTaskFromAsyncPattern)]
public static Func<TArg1, IObservable<TResult>> FromAsyncPattern<TArg1, TResult>(Func<TArg1, AsyncCallback, object?, IAsyncResult> begin, Func<IAsyncResult, TResult> end)
{
if (begin == null)
{
throw new ArgumentNullException(nameof(begin));
}
if (end == null)
{
throw new ArgumentNullException(nameof(end));
}
return s_impl.FromAsyncPattern(begin, end);
}
/// <summary>
/// Converts a Begin/End invoke function pair into an asynchronous function.
/// </summary>
/// <typeparam name="TArg1">The type of the first argument passed to the begin delegate.</typeparam>
/// <typeparam name="TArg2">The type of the second argument passed to the begin delegate.</typeparam>
/// <typeparam name="TResult">The type of the result returned by the end delegate.</typeparam>
/// <param name="begin">The delegate that begins the asynchronous operation.</param>
/// <param name="end">The delegate that ends the asynchronous operation.</param>
/// <returns>Function that can be used to start the asynchronous operation and retrieve the result as an observable sequence.</returns>
/// <exception cref="ArgumentNullException"><paramref name="begin"/> or <paramref name="end"/> is null.</exception>
/// <remarks>Each invocation of the resulting function will cause the asynchronous operation to be started. Subscription to the resulting sequence has no observable side-effect, and each subscription will produce the asynchronous operation's result.</remarks>
[Obsolete(Constants_Linq.UseTaskFromAsyncPattern)]
public static Func<TArg1, TArg2, IObservable<TResult>> FromAsyncPattern<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> begin, Func<IAsyncResult, TResult> end)View on GitHub (pinned to 94b5d5ab91)