{"record":{"id":"10f886fe965a997a","repo":"abpframework/abp","slug":"tickerq-does-not-support-dynamic-background-worker","errorCode":null,"errorMessage":"TickerQ does not support dynamic background worker registration at runtime. TickerQ uses FrozenDictionary for function registration, which requires all functions to be registered before the application starts. Please use Hangfire or Quartz provider for dynamic background workers.","messagePattern":"TickerQ does not support dynamic background worker registration at runtime\\. TickerQ uses FrozenDictionary for function registration, which requires all functions to be registered before the application starts\\. Please use Hangfire or Quartz provider for dynamic background workers\\.","errorType":"exception","errorClass":"AbpException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/TickerQDynamicBackgroundWorkerManager.cs","lineNumber":16,"sourceCode":"using System.Threading;\nusing System.Threading.Tasks;\nusing Volo.Abp.DependencyInjection;\n\nnamespace Volo.Abp.BackgroundWorkers.TickerQ;\n\n[Dependency(ReplaceServices = true)]\npublic class TickerQDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerManager, ISingletonDependency\n{\n    public virtual Task AddAsync(\n        string workerName,\n        DynamicBackgroundWorkerSchedule schedule,\n        DynamicBackgroundWorkerHandler handler,\n        CancellationToken cancellationToken = default)\n    {\n        throw new AbpException(\n            \"TickerQ does not support dynamic background worker registration at runtime. \" +\n            \"TickerQ uses FrozenDictionary for function registration, which requires all functions to be registered before the application starts. \" +\n            \"Please use Hangfire or Quartz provider for dynamic background workers.\");\n    }\n\n    public virtual Task<bool> RemoveAsync(string workerName, CancellationToken cancellationToken = default)\n    {\n        throw new AbpException(\n            \"TickerQ does not support dynamic background worker registration at runtime. \" +\n            \"Please use Hangfire or Quartz provider for dynamic background workers.\");\n    }\n\n    public virtual Task<bool> UpdateScheduleAsync(\n        string workerName,\n        DynamicBackgroundWorkerSchedule schedule,\n        CancellationToken cancellationToken = default)\n    {\n        throw new AbpException(","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/TickerQDynamicBackgroundWorkerManager.cs#L1-L34","documentation":"Thrown unconditionally by TickerQDynamicBackgroundWorkerManager.AddAsync because TickerQ uses a FrozenDictionary for function registration that is frozen at application startup. TickerQ cannot register background worker functions after the host has started, so the dynamic AddAsync contract is intentionally unsupported. The error directs you to Hangfire or Quartz, which do support runtime registration.","triggerScenarios":"Resolving IDynamicBackgroundWorkerManager at runtime (e.g. in an application service or hosted service) and calling AddAsync while the TickerQ background workers provider is the active implementation. This happens when the project references Volo.Abp.BackgroundWorkers.TickerQ and no Hangfire/Quartz provider overrides the default.","commonSituations":"Migrating from the in-memory dynamic worker manager to TickerQ without realizing TickerQ is static-registration only. Designing a feature that creates workers on demand (e.g. per-tenant scheduling) and then switching the provider to TickerQ for production reliability.","solutions":["Switch to the Hangfire (Volo.Abp.BackgroundWorkers.Hangfire) or Quartz (Volo.Abp.BackgroundWorkers.Quartz) provider, whose dynamic managers support runtime AddAsync.","If you must keep TickerQ, register all workers statically at startup (via AddBackgroundWorkerAsync or module configuration) instead of dynamically at runtime.","Before calling AddAsync, guard with IsRegistered or check the provider type to avoid the unsupported path."],"exampleFix":"// before — dynamic registration with TickerQ (throws)\npublic class MyService\n{\n    public MyService(IDynamicBackgroundWorkerManager dynamicManager)\n    {\n        dynamicManager.AddAsync(\"on-demand-worker\", schedule, handler).Wait();\n    }\n}\n\n// after — use Hangfire provider instead (in your module DependsOn)\n[DependsOn(typeof(AbpBackgroundWorkersHangfireModule))]\n// remove or do not depend on AbpBackgroundWorkersTickerQModule\npublic class MyAppModule : AbpModule { }","handlingStrategy":"try-catch","validationCode":"if (dynamicManager is Volo.Abp.BackgroundWorkers.TickerQ.TickerQDynamicBackgroundWorkerManager)\n{\n    throw new NotSupportedException(\"TickerQ does not support dynamic AddAsync; use Hangfire or Quartz.\");\n}","typeGuard":"static bool SupportsDynamicRegistration(IDynamicBackgroundWorkerManager mgr) => mgr is not Volo.Abp.BackgroundWorkers.TickerQ.TickerQDynamicBackgroundWorkerManager;","tryCatchPattern":"try { await dynamicManager.AddAsync(name, schedule, handler, ct); }\ncatch (AbpException ex) when (ex.Message.Contains(\"does not support dynamic background worker registration\"))\n{\n    logger.LogError(ex, \"Active provider does not support dynamic worker registration. Switch to Hangfire or Quartz.\");\n}","preventionTips":["If runtime worker registration is a requirement, depend on AbpBackgroundWorkersHangfireModule or AbpBackgroundWorkersQuartzModule instead of TickerQ.","Detect the active provider at startup and fail fast with a clear message if dynamic features are needed but unsupported.","Register all TickerQ workers statically at startup."],"tags":["tickerq","dynamic-workers","provider-limitation","unsupported-operation"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}