{"record":{"id":"848a37cc40aaff38","repo":"abpframework/abp","slug":"at-least-one-of-period-or-cronexpression-must","errorCode":null,"errorMessage":"At least one of 'Period' or 'CronExpression' must be set.","messagePattern":"At least one of 'Period' or 'CronExpression' must be set\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DynamicBackgroundWorkerSchedule.cs","lineNumber":24,"sourceCode":"{\n    public const int DefaultPeriod = 60000;\n\n    public int? Period { get; set; }\n\n    public string? CronExpression { get; set; }\n\n    public virtual void Validate()\n    {\n        if (Period.HasValue && Period.Value <= 0)\n        {\n            throw new ArgumentException(\n                $\"Period must be greater than 0 when provided. Given value: {Period.Value}.\",\n                nameof(Period));\n        }\n\n        if (Period == null && string.IsNullOrWhiteSpace(CronExpression))\n        {\n            throw new ArgumentException(\n                \"At least one of 'Period' or 'CronExpression' must be set.\");\n        }\n    }\n}\n","sourceCodeStart":6,"sourceCodeEnd":29,"githubUrl":"https://github.com/abpframework/abp/blob/7ed43b1931b9df46a50c0c59148a18645641d0df/framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DynamicBackgroundWorkerSchedule.cs#L6-L29","documentation":"Thrown by DynamicBackgroundWorkerSchedule.Validate when neither Period nor CronExpression is set (Period is null and CronExpression is null/whitespace). A dynamic worker must have at least one scheduling directive; with neither, the manager has no way to determine when to run the worker. Validate is called automatically by AddAsync and UpdateScheduleAsync.","triggerScenarios":"Constructing a DynamicBackgroundWorkerSchedule with default values (Period = null, CronExpression = null) and passing it to IDynamicBackgroundWorkerManager.AddAsync or UpdateScheduleAsync. Also thrown on a manual Validate() call on an unconfigured schedule.","commonSituations":"Building a schedule from optional configuration fields where both Period and CronExpression keys are absent. Intending to set Period but the property name was misspelled or the assignment was lost in a refactor. Passing a schedule object that was constructed but never populated.","solutions":["Set Period to a positive millisecond value (e.g. 60000) on the schedule.","Set CronExpression to a valid cron string (requires Hangfire/Quartz provider; the default in-memory manager rejects cron).","Read at least one scheduling value from configuration and ensure it is non-null before constructing the schedule."],"exampleFix":"// before — schedule has neither field set\nawait manager.AddAsync(\"worker\",\n    new DynamicBackgroundWorkerSchedule(), handler); // throws\n\n// after — set a period\nawait manager.AddAsync(\"worker\",\n    new DynamicBackgroundWorkerSchedule { Period = 60000 }, handler);","handlingStrategy":"validation","validationCode":"var schedule = new DynamicBackgroundWorkerSchedule();\nif (configuredPeriod.HasValue) schedule.Period = configuredPeriod;\nelse if (!string.IsNullOrWhiteSpace(configuredCron)) schedule.CronExpression = configuredCron;\nelse throw new InvalidOperationException(\"Configure either WorkerPeriod or WorkerCron in settings.\");\nschedule.Validate();","typeGuard":"static bool HasAtLeastOneSchedule(DynamicBackgroundWorkerSchedule s) => s.Period.HasValue || !string.IsNullOrWhiteSpace(s.CronExpression);","tryCatchPattern":null,"preventionTips":["Ensure at least one of Period or CronExpression is explicitly set when constructing the schedule.","Validate configuration keys exist before building the schedule.","Use DynamicBackgroundWorkerSchedule.DefaultPeriod as a fallback when configuration is optional."],"tags":["background-workers","dynamic-workers","argument-validation","scheduling","missing-value"],"backgroundTag":null,"analyzedSha":"7ed43b1931b9df46a50c0c59148a18645641d0df","analyzedAt":"2026-08-13T16:26:11.351Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}