dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'end')
Error message
Value cannot be null. (Parameter 'end')
What it means
FromAsyncPattern<T1..T5> adapts a Begin/End APM pair into a function returning an IAsyncObservable, and it throws ArgumentNullException with parameter name 'end' when the end callback (Func<IAsyncResult, Unit>) is null. A Begin/End pair is meaningless without the End delegate that extracts the result, so it is validated eagerly when the pattern is constructed. The exception is thrown at FromAsyncPattern call time, not when the returned function is invoked.
Solutions
- Pass the matching End method: FromAsyncPattern(begin, r => (Unit)EndXxx(r)) or via method group EndXxx.
- Verify reflection lookups (Type.GetMethod for the End method) are not returning null.
- Null-check both delegates before constructing the pattern and surface a domain-specific error.
Example fix
// before
var f = AsyncObservable.FromAsyncPattern<string, int, int, int, int>(req.BeginGetResponse, null);
// after
var f = AsyncObservable.FromAsyncPattern<string, int, int, int, int>(req.BeginGetResponse, r => { req.EndGetResponse(r); return Unit.Default; }); Defensive patterns
Strategy: validation
Validate before calling
if (begin is null || end is null) throw new InvalidOperationException("FromAsyncPattern requires a complete begin/end pair"); Type guard
bool IsCompletePair(Delegate begin, Delegate end) => begin is not null && end is not null;
Try / catch
try { var f = AsyncObservable.FromAsyncPattern<T1,T2,T3,T4,T5>(begin, end); }
catch (ArgumentNullException ex) when (ex.ParamName == "end") { /* log and rebuild with correct End method */ } Prevention
- Always pass Begin/End as matched method groups from the same object
- Check reflection GetMethod results for null before creating delegates
- Migrate legacy APM pairs to Task-returning methods where possible
When it happens
Trigger: Calling FromAsyncPattern(begin, end) with a null end delegate, e.g. the five-generic-argument overload where only begin was supplied or the end lambda was conditionally omitted.
Common situations: Migrating legacy APM (BeginXxx/EndXxx) APIs where the End method lookup via reflection returned null; wrapping WebRequest-style APIs with partially defined pairs.
Related errors
- Value cannot be null. (Parameter 'begin')
- Value cannot be null. (Parameter 'begin')
- Value cannot be null. (Parameter 'subscribeAsync')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/3b85eeea7ea8d8cf.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromAsyncPattern.Generated.cs:498
try
{
AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4);
}
catch (Exception ex)
{
return Throw<Unit>(ex);
}
return subject.AsAsyncObservable();
};
}
public static Func<T1, T2, T3, T4, T5, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
{
if (begin == null)
throw new ArgumentNullException(nameof(begin));
if (end == null)
throw new ArgumentNullException(nameof(end));
return (arg1, arg2, arg3, arg4, arg5) =>
{
var subject = new SequentialAsyncAsyncSubject<Unit>();
try
{
AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5);
}
catch (Exception ex)
{
return Throw<Unit>(ex);
}
return subject.AsAsyncObservable();
};
}
View on GitHub (pinned to 94b5d5ab91)