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

  1. Ensure all ABP NuGet packages are at the same version (run abp update or check all package versions) so AsyncPeriodicBackgroundWorkerBase.DoWorkAsync exists.
  2. If you overrode DoWorkAsync, keep the signature exactly as 'protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)' and do not change its accessibility.
  3. 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

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


AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13). Data as JSON: /api/errors/413ac33af7f48d94. Report an issue: GitHub.