abpframework/abp · error · AbpException
Given type ({workerType.AssemblyQualifiedName}) must impleme
Error message
Given type ({workerType.AssemblyQualifiedName}) must implement the {typeof(IBackgroundWorker).AssemblyQualifiedName} interface, but it doesn't! What it means
Thrown by BackgroundWorkersApplicationInitializationContextExtensions.AddBackgroundWorkerAsync(Type) when the provided type does not implement the IBackgroundWorker interface. ABP's background worker manager only accepts IBackgroundWorker instances; registering an arbitrary type would fail at resolution and execution time, so this guard fails fast with a clear message.
Source
Thrown at framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkersApplicationInitializationContextExtensions.cs:29
{
public async static Task<ApplicationInitializationContext> AddBackgroundWorkerAsync<TWorker>([NotNull] this ApplicationInitializationContext context, CancellationToken cancellationToken = default)
where TWorker : IBackgroundWorker
{
Check.NotNull(context, nameof(context));
await context.AddBackgroundWorkerAsync(typeof(TWorker), cancellationToken: cancellationToken);
return context;
}
public async static Task<ApplicationInitializationContext> AddBackgroundWorkerAsync([NotNull] this ApplicationInitializationContext context, [NotNull] Type workerType, CancellationToken cancellationToken = default)
{
Check.NotNull(context, nameof(context));
Check.NotNull(workerType, nameof(workerType));
if (!workerType.IsAssignableTo<IBackgroundWorker>())
{
throw new AbpException($"Given type ({workerType.AssemblyQualifiedName}) must implement the {typeof(IBackgroundWorker).AssemblyQualifiedName} interface, but it doesn't!");
}
if (cancellationToken == default)
{
var hostApplicationLifetime = context.ServiceProvider.GetService<IHostApplicationLifetime>();
if (hostApplicationLifetime != null)
{
cancellationToken = hostApplicationLifetime.ApplicationStopping;
}
}
await context.ServiceProvider
.GetRequiredService<IBackgroundWorkerManager>()
.AddAsync((IBackgroundWorker)context.ServiceProvider.GetRequiredService(workerType), cancellationToken);
return context;
}
}View on GitHub (pinned to 7ed43b1931)
Solutions
- Make the class implement IBackgroundWorker, typically by inheriting from AsyncPeriodicBackgroundWorkerBase, PeriodicBackgroundWorkerBase, or HangfireBackgroundWorkerBase/QuartzBackgroundWorkerBase.
- If selecting types dynamically, filter with typeof(IBackgroundWorker).IsAssignableFrom(type) before calling AddBackgroundWorkerAsync.
- Verify the type name in the error message; correct it to the intended worker type.
Example fix
// before — class is not a background worker
public class ReportGenerator
{
public void Generate() { ... }
}
context.AddBackgroundWorkerAsync(typeof(ReportGenerator)); // throws
// after — inherit from a periodic worker base
public class ReportGeneratorWorker : AsyncPeriodicBackgroundWorkerBase
{
public ReportGeneratorWorker() { Period = 60000; }
protected override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
// generate report
return Task.CompletedTask;
}
}
context.AddBackgroundWorkerAsync<ReportGeneratorWorker>(); Defensive patterns
Strategy: type-guard
Validate before calling
Type workerType = typeof(MyClass);
if (!typeof(IBackgroundWorker).IsAssignableFrom(workerType))
{
throw new InvalidOperationException($"{workerType.FullName} does not implement IBackgroundWorker.");
}
await context.AddBackgroundWorkerAsync(workerType, cancellationToken); Type guard
static bool IsBackgroundWorker(Type t) => typeof(IBackgroundWorker).IsAssignableFrom(t);
Prevention
- Use the generic AddBackgroundWorkerAsync<TWorker>() overload which enforces the constraint at compile time.
- When scanning assemblies, filter candidates with typeof(IBackgroundWorker).IsAssignableFrom(type).
- Ensure custom workers inherit from a recognized base (AsyncPeriodicBackgroundWorkerBase, etc.).
When it happens
Trigger: Calling context.AddBackgroundWorkerAsync(typeof(NonWorkerClass)) where NonWorkerClass does not implement IBackgroundWorker. Passing a type loaded via reflection (e.g. Type.GetType(name)) that turns out to be a plain service or DTO rather than a worker.
Common situations: Dynamically scanning an assembly for worker types and passing every concrete type without filtering for IBackgroundWorker. Copying an AddBackgroundWorkerAsync line and changing the type to a class that is not a worker. Forgetting to inherit from PeriodicBackgroundWorkerBase / AsyncPeriodicBackgroundWorkerBase or implement IBackgroundWorker on a custom worker.
Related errors
- Both 'Period' and 'CronExpression' are not set for {worker.G
- The following background job(s) are configured for more than
- The distributed lock name '{configuration.LockName}' is used
- No background job is registered for the args type '{argsType
- Cannot convert period: {period} to cron expression, use Hang
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/38c297065a8ee153.
Report an issue: GitHub.