apache/superset · error · ReportScheduleCrontabNotValidError
Invalid crontab schedule: %(cron_schedule)s never matches a
Error message
Invalid crontab schedule: %(cron_schedule)s never matches a valid date
What it means
Raised when croniter(cron_schedule) raises CroniterBadDateError, meaning the crontab expression can never match a valid date. Superset wraps it as ReportScheduleCrontabNotValidError so the API returns an actionable message naming the offending crontab instead of a raw croniter traceback. It is part of crontab validation on report/alert create and update.
Source
Thrown at superset/commands/report/base.py:360
# Since configuration is in minutes, we only need to validate
# in case `minimum_interval` is <= 120 (2min)
if minimum_interval < 120:
return
iterations = 60 if minimum_interval <= 3660 else 24
try:
schedule = croniter(cron_schedule)
current_exec = next(schedule)
for _i in range(iterations):
next_exec = next(schedule)
diff, current_exec = next_exec - current_exec, next_exec
if int(diff) < minimum_interval:
raise ReportScheduleFrequencyNotAllowed(
report_type=report_type, minimum_interval=minimum_interval
)
except CroniterBadDateError as ex:
raise ReportScheduleCrontabNotValidError(
cron_schedule=cron_schedule
) from ex
View on GitHub (pinned to f4587218dd)
Solutions
- Fix the impossible date: use a real combination like '0 0 31 1,3,5,7,8,10,12 *' (31st only in 31-day months) or '59 23 L * *' style last-day syntax if supported
- Pre-validate the expression with croniter before calling the API
- If you intended 'last day of month', use a day-of-week/last-day form croniter accepts
Example fix
# before
crontab = '0 0 31 2 *' # Feb 31 never exists -> CroniterBadDateError
# after
from croniter import croniter
croniter.is_valid('0 0 28 2 *') # True; use a real date Defensive patterns
Strategy: validation
Validate before calling
from croniter import croniter
if not croniter.is_valid(crontab):
raise ValueError(f'Invalid crontab: {crontab!r}') # catches never-matching dates Type guard
def is_valid_crontab(expr: str) -> bool:
return croniter.is_valid(expr) Try / catch
try:
CreateReportCommand(user, payload).run()
except ReportScheduleCrontabNotValidError as ex:
show_error(f'{ex.cron_schedule} never matches a valid date; fix the expression') Prevention
- Always run croniter.is_valid on user-supplied or generated crontabs before persisting
- Avoid day-of-month 29-31 combined with months that lack those days
- Prefer generated schedules from a calendar library over hand-typed dates
When it happens
Trigger: Submitting a crontab such as '0 0 31 2 *' (Feb 31) or '0 0 30 2 *' (Feb 30) — dates that never exist — to the report/alert API. Any five-field expression whose day-of-month/month combination is impossible.
Common situations: Hand-written crontabs copied from a spec ('run on the 31st of February'); UI or script generating end-of-month schedules without clamping; typos in the month field.
Related errors
- %(report_type)s schedule frequency exceeding limit. Please c
- validation_error
- Resource already has an attached report.
- Report Schedule parameters are invalid.
- Report Schedule executor user %(username)s was not found.
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/59f782e7be4ef82f.
Report an issue: GitHub.