abpframework/abp · critical · AbpException
Could not find 'DoWorkAsync' method on type '{workerType.Ful
Error message
Could not find 'DoWorkAsync' method on type '{workerType.FullName}'. What it means
Thrown by AbpTickerQPeriodicBackgroundWorkerInvoker when reflecting over a worker that is an AsyncPeriodicBackgroundWorkerBase subclass, but the non-public instance method 'DoWorkAsync' cannot be found. ABP invokes this protected method via reflection+expression compilation to run the worker's periodic work. Under normal ABP versions the method always exists on the base class, so this typically signals a version mismatch or an unconventional subclass that hid/renamed it.
Source
Thrown at framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQPeriodicBackgroundWorkerInvoker.cs:31
private readonly Action<PeriodicBackgroundWorkerBase, PeriodicBackgroundWorkerContext>? _doWorkDelegate;
protected IBackgroundWorker Worker { get; }
protected IServiceProvider ServiceProvider { get; }
public AbpTickerQPeriodicBackgroundWorkerInvoker(IBackgroundWorker worker, IServiceProvider serviceProvider)
{
Worker = worker;
ServiceProvider = serviceProvider;
switch (worker)
{
case AsyncPeriodicBackgroundWorkerBase:
{
var workerType = worker.GetType();
var method = workerType.GetMethod("DoWorkAsync", BindingFlags.Instance | BindingFlags.NonPublic);
if (method == null)
{
throw new AbpException($"Could not find 'DoWorkAsync' method on type '{workerType.FullName}'.");
}
var instanceParam = Expression.Parameter(typeof(AsyncPeriodicBackgroundWorkerBase), "worker");
var contextParam = Expression.Parameter(typeof(PeriodicBackgroundWorkerContext), "context");
var call = Expression.Call(Expression.Convert(instanceParam, workerType), method, contextParam);
var lambda = Expression.Lambda<Func<AsyncPeriodicBackgroundWorkerBase, PeriodicBackgroundWorkerContext, Task>>(call, instanceParam, contextParam);
_doWorkAsyncDelegate = lambda.Compile();
break;
}
case PeriodicBackgroundWorkerBase:
{
var workerType = worker.GetType();
var method = workerType.GetMethod("DoWork", BindingFlags.Instance | BindingFlags.NonPublic);
if (method == null)
{
throw new AbpException($"Could not find 'DoWork' method on type '{workerType.FullName}'.");
}
View on GitHub (pinned to 7ed43b1931)
Solutions
- Ensure all ABP NuGet packages are at the same version (run abp update or check all package versions) so AsyncPeriodicBackgroundWorkerBase.DoWorkAsync exists.
- If you overrode DoWorkAsync, keep the signature exactly as 'protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)' and do not change its accessibility.
- If the issue is proxy-related, verify the worker is registered correctly in DI and not wrapped by a custom interceptor that strips the method.
Example fix
// before — method accidentally made public with a different signature
public class MyWorker : AsyncPeriodicBackgroundWorkerBase
{
public new Task DoWorkAsync() { ... }
}
// after — correct protected override
public class MyWorker : AsyncPeriodicBackgroundWorkerBase
{
Period = 60000;
protected override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
return Task.CompletedTask;
}
} Defensive patterns
Strategy: validation
Validate before calling
var method = worker.GetType().GetMethod("DoWorkAsync", BindingFlags.Instance | BindingFlags.NonPublic);
if (method == null)
{
throw new InvalidOperationException($"Worker {worker.GetType().FullName} is missing DoWorkAsync; check ABP package versions and method signature.");
} Type guard
static bool HasDoWorkAsync(Type workerType) => workerType.GetMethod("DoWorkAsync", BindingFlags.Instance | BindingFlags.NonPublic) != null; Prevention
- Keep all ABP NuGet packages at the same version.
- When overriding DoWorkAsync, match the exact protected override signature.
- Prefer AsyncPeriodicBackgroundWorkerBase over the synchronous base for new workers.
When it happens
Trigger: Registering an AsyncPeriodicBackgroundWorkerBase-derived worker whose type, after proxy generation or inheritance, no longer exposes a non-public DoWorkAsync(PeriodicBackgroundWorkerContext) method. Most commonly caused by a framework version mismatch where the installed Volo.Abp package does not declare DoWorkAsync on the base class, or a custom override changed the method signature/accessibility.
Common situations: Upgrading or downgrading the ABP framework packages inconsistently (some packages at one version, others at another) where the base class API changed. A custom worker that accidentally shadows DoWorkAsync with a different signature or makes it public, breaking the BindingFlags.NonPublic lookup. A dynamic-proxy or AOP weaving that altered method visibility.
Related errors
- Could not find 'DoWork' method on type '{workerType.FullName
- Both 'Period' and 'CronExpression' are not set for {worker.G
- Cannot convert period: {period} to cron expression.
- Background job execution is disabled. This method should not
- Job args types cannot contain null.
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/413ac33af7f48d94.
Report an issue: GitHub.