{"record":{"id":"38c297065a8ee153","repo":"abpframework/abp","slug":"given-type-workertype-assemblyqualifiedname-mu","errorCode":null,"errorMessage":"Given type ({workerType.AssemblyQualifiedName}) must implement the {typeof(IBackgroundWorker).AssemblyQualifiedName} interface, but it doesn't!","messagePattern":"Given type \\((.+?)\\) must implement the (.+?) interface, but it doesn't!","errorType":"exception","errorClass":"AbpException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkersApplicationInitializationContextExtensions.cs","lineNumber":29,"sourceCode":"{\n    public async static Task<ApplicationInitializationContext> AddBackgroundWorkerAsync<TWorker>([NotNull] this ApplicationInitializationContext context, CancellationToken cancellationToken = default)\n        where TWorker : IBackgroundWorker\n    {\n        Check.NotNull(context, nameof(context));\n\n        await context.AddBackgroundWorkerAsync(typeof(TWorker), cancellationToken: cancellationToken);\n\n        return context;\n    }\n\n    public async static Task<ApplicationInitializationContext> AddBackgroundWorkerAsync([NotNull] this ApplicationInitializationContext context, [NotNull] Type workerType, CancellationToken cancellationToken = default)\n    {\n        Check.NotNull(context, nameof(context));\n        Check.NotNull(workerType, nameof(workerType));\n\n        if (!workerType.IsAssignableTo<IBackgroundWorker>())\n        {\n            throw new AbpException($\"Given type ({workerType.AssemblyQualifiedName}) must implement the {typeof(IBackgroundWorker).AssemblyQualifiedName} interface, but it doesn't!\");\n        }\n\n        if (cancellationToken == default)\n        {\n            var hostApplicationLifetime = context.ServiceProvider.GetService<IHostApplicationLifetime>();\n            if (hostApplicationLifetime != null)\n            {\n                cancellationToken = hostApplicationLifetime.ApplicationStopping;\n            }\n        }\n\n        await context.ServiceProvider\n            .GetRequiredService<IBackgroundWorkerManager>()\n            .AddAsync((IBackgroundWorker)context.ServiceProvider.GetRequiredService(workerType), cancellationToken);\n\n        return context;\n    }\n}","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/BackgroundWorkersApplicationInitializationContextExtensions.cs#L11-L47","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — class is not a background worker\npublic class ReportGenerator\n{\n    public void Generate() { ... }\n}\ncontext.AddBackgroundWorkerAsync(typeof(ReportGenerator)); // throws\n\n// after — inherit from a periodic worker base\npublic class ReportGeneratorWorker : AsyncPeriodicBackgroundWorkerBase\n{\n    public ReportGeneratorWorker() { Period = 60000; }\n    protected override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)\n    {\n        // generate report\n        return Task.CompletedTask;\n    }\n}\ncontext.AddBackgroundWorkerAsync<ReportGeneratorWorker>();","handlingStrategy":"type-guard","validationCode":"Type workerType = typeof(MyClass);\nif (!typeof(IBackgroundWorker).IsAssignableFrom(workerType))\n{\n    throw new InvalidOperationException($\"{workerType.FullName} does not implement IBackgroundWorker.\");\n}\nawait context.AddBackgroundWorkerAsync(workerType, cancellationToken);","typeGuard":"static bool IsBackgroundWorker(Type t) => typeof(IBackgroundWorker).IsAssignableFrom(t);","tryCatchPattern":null,"preventionTips":["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.)."],"tags":["background-workers","type-validation","registration","startup"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}