abpframework/abp · critical · AbpException
Could not find 'DoWork' method on type '{workerType.FullName
Error message
Could not find 'DoWork' method on type '{workerType.FullName}'. What it means
Thrown by AbpTickerQPeriodicBackgroundWorkerInvoker when reflecting over a PeriodicBackgroundWorkerBase subclass and the non-public instance method 'DoWork' cannot be found. ABP compiles a delegate to this protected method to drive the worker's periodic execution. The method is part of the ABP base class contract; its absence indicates a version mismatch or an incorrectly overridden worker.
Source
Thrown at framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQPeriodicBackgroundWorkerInvoker.cs:47
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}'.");
}
var instanceParam = Expression.Parameter(typeof(PeriodicBackgroundWorkerBase), "worker");
var contextParam = Expression.Parameter(typeof(PeriodicBackgroundWorkerContext), "context");
var call = Expression.Call(Expression.Convert(instanceParam, workerType), method, contextParam);
var lambda = Expression.Lambda<Action<PeriodicBackgroundWorkerBase, PeriodicBackgroundWorkerContext>>(call, instanceParam, contextParam);
_doWorkDelegate = lambda.Compile();
break;
}
}
}
public virtual async Task DoWorkAsync(TickerFunctionContext context, CancellationToken cancellationToken = default)
{
var workerContext = new PeriodicBackgroundWorkerContext(ServiceProvider);
switch (Worker)
{
case AsyncPeriodicBackgroundWorkerBase asyncPeriodicBackgroundWorker:View on GitHub (pinned to 7ed43b1931)
Solutions
- Align all ABP package versions so PeriodicBackgroundWorkerBase.DoWork exists with the expected signature and accessibility.
- If overriding, use 'protected override void DoWork(PeriodicBackgroundWorkerContext workerContext)' exactly.
- Prefer AsyncPeriodicBackgroundWorkerBase over the synchronous base for new workers, as it is the recommended base class.
Example fix
// before — wrong signature/access
public class MyWorker : PeriodicBackgroundWorkerBase
{
private void DoWork() { ... } // wrong
}
// after
public class MyWorker : PeriodicBackgroundWorkerBase
{
Period = 60000;
protected override void DoWork(PeriodicBackgroundWorkerContext workerContext) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
var method = worker.GetType().GetMethod("DoWork", BindingFlags.Instance | BindingFlags.NonPublic);
if (method == null)
{
throw new InvalidOperationException($"Worker {worker.GetType().FullName} is missing DoWork; check ABP package versions and method signature.");
} Type guard
static bool HasDoWork(Type workerType) => workerType.GetMethod("DoWork", BindingFlags.Instance | BindingFlags.NonPublic) != null; Prevention
- Keep all ABP NuGet packages version-aligned.
- Override DoWork with the exact 'protected override void DoWork(PeriodicBackgroundWorkerContext)' signature.
- Prefer the async base class for new workers to avoid the synchronous reflection path.
When it happens
Trigger: Registering a worker derived from the synchronous PeriodicBackgroundWorkerBase whose DoWork(PeriodicBackgroundWorkerContext) method is not resolvable via BindingFlags.Instance | BindingFlags.NonPublic. Happens when the ABP packages are version-inconsistent or a subclass shadowed the method incorrectly.
Common situations: Mixing ABP package versions where the base class no longer declares DoWork as protected. Overriding DoWork but changing its access modifier (e.g. making it private or renaming it). A weaving/proxy layer that altered method metadata.
Related errors
- Could not find 'DoWorkAsync' method on type '{workerType.Ful
- 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/1aacc71337006438.
Report an issue: GitHub.