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

  1. Make the class implement IBackgroundWorker, typically by inheriting from AsyncPeriodicBackgroundWorkerBase, PeriodicBackgroundWorkerBase, or HangfireBackgroundWorkerBase/QuartzBackgroundWorkerBase.
  2. If selecting types dynamically, filter with typeof(IBackgroundWorker).IsAssignableFrom(type) before calling AddBackgroundWorkerAsync.
  3. 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

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


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