dotnet/reactive · error · ArgumentNullException
begin
Error message
begin
What it means
The two-argument FromAsyncPattern<TArg1,TArg2,TResult> overload throws ArgumentNullException('begin') when the Func<TArg1,TArg2,AsyncCallback,object?,IAsyncResult> begin delegate is null. The begin delegate starts the asynchronous operation for each invocation of the resulting function; it is required and checked eagerly. This APM-based overload family is also marked obsolete in favor of the Task-based API.
Solutions
- Provide a non-null begin delegate invoking the underlying BeginXxx method with both arguments
- Assert delegate non-nullness before calling FromAsyncPattern
- Replace with Observable.FromAsync((a,b) => Task-returning method)
Example fix
// before
var f = Observable.FromAsyncPattern<string, int, byte[]>(null, end);
// after
var f = Observable.FromAsyncPattern<string, int, byte[]>(
(path, off, cb, st) => fs.BeginRead(buffer, off, size, cb, st),
iar => fs.EndRead(iar)); Defensive patterns
Strategy: validation
Validate before calling
if (begin == null) throw new InvalidOperationException("begin delegate must be provided");
var f = Observable.FromAsyncPattern<TArg1, TArg2, TResult>(begin, end); Type guard
static bool HasBegin<TArg1,TArg2,TResult>(Func<TArg1, TArg2, AsyncCallback, object?, IAsyncResult> begin) => begin != null;
Try / catch
try
{
var f = Observable.FromAsyncPattern<TArg1, TArg2, TResult>(begin, end);
}
catch (ArgumentNullException ex) when (ex.ParamName == "begin")
{
// repair the begin delegate
} Prevention
- Reference BeginXxx method groups directly
- Check dynamic delegate resolution results
- Prefer Observable.FromAsync with async lambdas
When it happens
Trigger: Observable.FromAsyncPattern<TArg1,TArg2,TResult>(null, end) with two arguments and a valid end delegate.
Common situations: Reflection-based delegate construction failing silently; refactoring that removed a BeginXxx wrapper; passing a method group whose overload resolution failed and produced null in dynamic code.
Related errors
- Value cannot be null. (Parameter 'end')
- end
- 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/e501c7d241c0bec5.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Async.cs:84
}
/// <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)
{
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="TArg3">The type of the third 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>View on GitHub (pinned to 94b5d5ab91)