abpframework/abp · error · AbpException

TickerQ does not support dynamic background worker registrat

Error message

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.

What it means

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.

Source

Thrown at framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/TickerQDynamicBackgroundWorkerManager.cs:16

using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;

namespace Volo.Abp.BackgroundWorkers.TickerQ;

[Dependency(ReplaceServices = true)]
public class TickerQDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerManager, ISingletonDependency
{
    public virtual Task AddAsync(
        string workerName,
        DynamicBackgroundWorkerSchedule schedule,
        DynamicBackgroundWorkerHandler handler,
        CancellationToken cancellationToken = default)
    {
        throw new AbpException(
            "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.");
    }

    public virtual Task<bool> RemoveAsync(string workerName, CancellationToken cancellationToken = default)
    {
        throw new AbpException(
            "TickerQ does not support dynamic background worker registration at runtime. " +
            "Please use Hangfire or Quartz provider for dynamic background workers.");
    }

    public virtual Task<bool> UpdateScheduleAsync(
        string workerName,
        DynamicBackgroundWorkerSchedule schedule,
        CancellationToken cancellationToken = default)
    {
        throw new AbpException(

View on GitHub (pinned to 7ed43b1931)

Solutions

  1. Switch to the Hangfire (Volo.Abp.BackgroundWorkers.Hangfire) or Quartz (Volo.Abp.BackgroundWorkers.Quartz) provider, whose dynamic managers support runtime AddAsync.
  2. If you must keep TickerQ, register all workers statically at startup (via AddBackgroundWorkerAsync or module configuration) instead of dynamically at runtime.
  3. Before calling AddAsync, guard with IsRegistered or check the provider type to avoid the unsupported path.

Example fix

// before — dynamic registration with TickerQ (throws)
public class MyService
{
    public MyService(IDynamicBackgroundWorkerManager dynamicManager)
    {
        dynamicManager.AddAsync("on-demand-worker", schedule, handler).Wait();
    }
}

// after — use Hangfire provider instead (in your module DependsOn)
[DependsOn(typeof(AbpBackgroundWorkersHangfireModule))]
// remove or do not depend on AbpBackgroundWorkersTickerQModule
public class MyAppModule : AbpModule { }
Defensive patterns

Strategy: try-catch

Validate before calling

if (dynamicManager is Volo.Abp.BackgroundWorkers.TickerQ.TickerQDynamicBackgroundWorkerManager)
{
    throw new NotSupportedException("TickerQ does not support dynamic AddAsync; use Hangfire or Quartz.");
}

Type guard

static bool SupportsDynamicRegistration(IDynamicBackgroundWorkerManager mgr) => mgr is not Volo.Abp.BackgroundWorkers.TickerQ.TickerQDynamicBackgroundWorkerManager;

Try / catch

try { await dynamicManager.AddAsync(name, schedule, handler, ct); }
catch (AbpException ex) when (ex.Message.Contains("does not support dynamic background worker registration"))
{
    logger.LogError(ex, "Active provider does not support dynamic worker registration. Switch to Hangfire or Quartz.");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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