HangfireIO/Hangfire · error · ArgumentNullException
task
Error message
task
What it means
Thrown by TaskExtensions.GetTaskLikeResult (internal) when the Task argument is null. The method calls task.GetAwaiter().GetResult() to ensure completion before extracting a result, so a null task would NRE.
Source
Thrown at src/Hangfire.Core/Processing/TaskExtensions.cs:139
{
var asTask = type.GetRuntimeMethod("AsTask", EmptyTypes);
if (asTask != null && asTask.IsPublic && !asTask.IsStatic &&
typeof(Task).GetTypeInfo().IsAssignableFrom(asTask.ReturnType.GetTypeInfo()))
{
getTaskFunc = obj => (Task) asTask.Invoke(obj, null);
return true;
}
}
}
getTaskFunc = null;
return false;
}
public static object GetTaskLikeResult([NotNull] this Task task, object obj, Type returnType)
{
if (task == null) throw new ArgumentNullException(nameof(task));
if (task != obj)
{
// We shouldn't call GetAwaiter/GetResult on ValueTask directly, because
// there may be a race condition as tells us this article:
// https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/#user-content-valid-consumption-patterns-for-valuetasks
// So we are waiting on task, returned by the AsTask method to ensure it's
// completed, before querying for the result.
task.GetAwaiter().GetResult();
}
// ReturnType is used instead of task.GetType, because we should return `null` result,
// when method is returning non-generic Task. However async state machines may use
// Task<VoidTaskResult> or Task<VoidResult> for these cases, and the number of such
// void types is pretty high. So it's much safer to call GetAwaiter/GetResult on an
// original result object.
// Awaitable type must have a public parameterless GetAwaiter instance method, ...View on GitHub (pinned to c236dd0f93)
Solutions
- Ensure async job methods return a Task (never null) — async methods always do; the issue is sync methods declaring Task return types and returning null.
- Audit job methods that declare Task/Task<T> returns for `return null;` or missing return statements.
- If wrapping invocation, coalesce null to Task.CompletedTask before this path.
Example fix
// before
public Task RunAsync() { return null; } // job returning null Task
// after
public Task RunAsync() { return DoWorkAsync(); }
// or, for a no-op: public Task RunAsync() => Task.CompletedTask; Defensive patterns
Strategy: validation
Validate before calling
if (task == null) throw new ArgumentNullException(nameof(task)); return task.GetTaskLikeResult(obj, returnType);
Prevention
- Ensure async job methods always return a Task (never null).
- Audit job methods declared as Task/Task<T> for `return null;`.
- Coalesce null tasks to Task.CompletedTask when wrapping invocation.
When it happens
Trigger: Calling task.GetTaskLikeResult(obj, returnType) where task is null. Reached when Hangfire's invocation pipeline resolves a job's return task to null (e.g., a job method returned null where a Task was expected).
Common situations: An async job method returns null instead of a Task (a coding error in the job); a ValueTask/Task conversion path yielded null; reflection invocation produced a null task object.
Related errors
AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13).
Data as JSON: /api/errors/89ed6cf9efe4e999.
Report an issue: GitHub.