{"record":{"id":"01bb308628b4f753","repo":"abpframework/abp","slug":"the-default-in-memory-background-worker-manager-do","errorCode":null,"errorMessage":"The default in-memory background worker manager does not support CronExpression for dynamic worker '{workerName}'. Please clear CronExpression and use Period-based scheduling, or use a scheduler-backed provider (Hangfire or Quartz).","messagePattern":"The default in-memory background worker manager does not support CronExpression for dynamic worker '(.+?)'\\. Please clear CronExpression and use Period-based scheduling, or use a scheduler-backed provider \\(Hangfire or Quartz\\)\\.","errorType":"exception","errorClass":"AbpException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DefaultDynamicBackgroundWorkerManager.cs","lineNumber":47,"sourceCode":"        _dynamicWorkers = new ConcurrentDictionary<string, InMemoryDynamicBackgroundWorker>();\n        _semaphore = new SemaphoreSlim(1, 1);\n    }\n\n    public virtual async Task AddAsync(\n        string workerName,\n        DynamicBackgroundWorkerSchedule schedule,\n        DynamicBackgroundWorkerHandler handler,\n        CancellationToken cancellationToken = default)\n    {\n        Check.NotNullOrWhiteSpace(workerName, nameof(workerName));\n        Check.NotNull(schedule, nameof(schedule));\n        Check.NotNull(handler, nameof(handler));\n\n        schedule.Validate();\n\n        if (!schedule.CronExpression.IsNullOrWhiteSpace())\n        {\n            throw new AbpException(\n                $\"The default in-memory background worker manager does not support CronExpression for dynamic worker '{workerName}'. \" +\n                \"Please clear CronExpression and use Period-based scheduling, or use a scheduler-backed provider (Hangfire or Quartz).\");\n        }\n\n        await _semaphore.WaitAsync(cancellationToken);\n        try\n        {\n            if (_isDisposed)\n            {\n                throw new ObjectDisposedException(nameof(DefaultDynamicBackgroundWorkerManager));\n            }\n\n            if (_dynamicWorkers.TryRemove(workerName, out var existingWorker))\n            {\n                await existingWorker.StopAsync(cancellationToken);\n                Logger.LogInformation(\"Replaced existing dynamic worker: {WorkerName}\", workerName);\n            }\n","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DefaultDynamicBackgroundWorkerManager.cs#L29-L65","documentation":"Thrown by DefaultDynamicBackgroundWorkerManager.AddAsync when the supplied DynamicBackgroundWorkerSchedule has a non-empty CronExpression. The default in-memory dynamic worker manager only supports Period-based scheduling (it uses an AbpAsyncTimer); it has no cron engine. The error tells you to drop CronExpression and use Period, or switch to Hangfire/Quartz which support cron.","triggerScenarios":"Calling AddAsync on IDynamicBackgroundWorkerManager (resolved as DefaultDynamicBackgroundWorkerManager, the built-in implementation) with a DynamicBackgroundWorkerSchedule where CronExpression is set (e.g. \"0 * * * *\"). This happens when no Hangfire or Quartz background workers module is loaded, so the default in-memory manager is active.","commonSituations":"Developing with cron-based scheduling locally where the default manager is used (no Hangfire/Quartz dependency), then deploying the same schedule to production. Copying a schedule object that was built for Hangfire into a project without the Hangfire provider.","solutions":["Clear CronExpression and set a Period (in ms) on the schedule: new DynamicBackgroundWorkerSchedule { Period = 60000 }.","Add the Hangfire or Quartz background workers module to the project so the cron-capable dynamic manager resolves instead of the default.","If you need both cron and the in-memory manager, reconsider — use a provider that supports cron."],"exampleFix":"// before — cron expression with default in-memory manager (throws)\nawait dynamicManager.AddAsync(\"cron-worker\",\n    new DynamicBackgroundWorkerSchedule { CronExpression = \"0 */5 * * *\" },\n    handler);\n\n// after — use Period instead\nawait dynamicManager.AddAsync(\"periodic-worker\",\n    new DynamicBackgroundWorkerSchedule { Period = 300000 }, // 5 minutes\n    handler);","handlingStrategy":"validation","validationCode":"var schedule = new DynamicBackgroundWorkerSchedule { Period = 60000 };\nif (!schedule.CronExpression.IsNullOrWhiteSpace() && dynamicManager is DefaultDynamicBackgroundWorkerManager)\n{\n    throw new NotSupportedException(\"Default in-memory manager does not support cron; clear CronExpression or use Hangfire/Quartz.\");\n}","typeGuard":"static bool ManagerSupportsCron(IDynamicBackgroundWorkerManager mgr) => mgr is not DefaultDynamicBackgroundWorkerManager;","tryCatchPattern":"try { await dynamicManager.AddAsync(name, schedule, handler, ct); }\ncatch (AbpException ex) when (ex.Message.Contains(\"does not support CronExpression\"))\n{\n    logger.LogError(ex, \"Clear CronExpression and use Period, or switch to Hangfire/Quartz.\");\n}","preventionTips":["Default to Period-based schedules when using the in-memory manager.","Detect the active provider at startup and reject cron-based schedules early.","Add the Hangfire or Quartz module if cron scheduling is required."],"tags":["background-workers","dynamic-workers","cron","provider-limitation","in-memory"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}