Skip to content

Commit d22792a

Browse files
committed
fix(schedule): reject cron expressions that never match
Since cron-parser 5.7, an expression such as `0 0 31 4,6 *` parses but throws from next() because no date matches. Validation only parsed, so the raw parser error escaped from run() instead of E_INVALID_CRON_EXPRESSION. Ask for one occurrence while validating.
1 parent cfd6dce commit d22792a

2 files changed

Lines changed: 11 additions & 2 deletions

File tree

‎src/schedule_builder.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,11 @@ export class ScheduleBuilder<TPayload = unknown> implements PromiseLike<Schedule
148148
])
149149
}
150150

151-
// Validate cron expression
151+
// Validate cron expression. Some expressions parse but never match
152+
// (`0 0 31 4,6 *`), and only throw once asked for an occurrence.
152153
if (this.#cronExpression) {
153154
try {
154-
CronExpressionParser.parse(this.#cronExpression, { tz: this.#timezone })
155+
CronExpressionParser.parse(this.#cronExpression, { tz: this.#timezone }).next()
155156
} catch (error) {
156157
throw new errors.E_INVALID_CRON_EXPRESSION(
157158
[this.#cronExpression, (error as Error).message],

‎tests/schedule.spec.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,14 @@ test.group('ScheduleBuilder', (group) => {
227227
}
228228
})
229229

230+
test('should throw for a cron expression that never matches', async ({ assert }) => {
231+
// Parses fine, but April and June have no 31st
232+
await assert.rejects(
233+
() => new ScheduleBuilder('NeverJob', {}).cron('0 0 31 4,6 *').run(),
234+
errors.E_INVALID_CRON_EXPRESSION
235+
)
236+
})
237+
230238
test('should be thenable for auto-run', async ({ assert }) => {
231239
const builder = new ScheduleBuilder('SyncJob', { source: 'api' })
232240

0 commit comments

Comments
 (0)