{"record":{"id":"88911f9e60c60eee","repo":"apache/superset","slug":"report-type-s-schedule-frequency-exceeding-limit","errorCode":null,"errorMessage":"%(report_type)s schedule frequency exceeding limit. Please configure a schedule with a minimum interval of %(minimum_interval)d minutes per execution.","messagePattern":"(.+?) schedule frequency exceeding limit\\. Please configure a schedule with a minimum interval of (.+?) minutes per execution\\.","errorType":"validation","errorClass":"ReportScheduleFrequencyNotAllowed","httpStatus":422,"severity":"error","filePath":"superset/commands/report/base.py","lineNumber":356,"sourceCode":"                \"Invalid value for %s: %s\", config_key, minimum_interval, exc_info=True\n            )\n            return\n\n        # Since configuration is in minutes, we only need to validate\n        # in case `minimum_interval` is <= 120 (2min)\n        if minimum_interval < 120:\n            return\n\n        iterations = 60 if minimum_interval <= 3660 else 24\n        try:\n            schedule = croniter(cron_schedule)\n            current_exec = next(schedule)\n\n            for _i in range(iterations):\n                next_exec = next(schedule)\n                diff, current_exec = next_exec - current_exec, next_exec\n                if int(diff) < minimum_interval:\n                    raise ReportScheduleFrequencyNotAllowed(\n                        report_type=report_type, minimum_interval=minimum_interval\n                    )\n        except CroniterBadDateError as ex:\n            raise ReportScheduleCrontabNotValidError(\n                cron_schedule=cron_schedule\n            ) from ex\n","sourceCodeStart":338,"sourceCodeEnd":363,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/report/base.py#L338-L363","documentation":"Raised by ReportScheduleCommand.validate_crontab_logic when a report/alert crontab fires more frequently than ALERT_REPORTS_MINIMAL_INTERVAL allows. The code iterates the next 60 (or 24) cron matches with croniter and measures the gap between consecutive executions; any gap below minimum_interval (only enforced when >= 120 seconds) triggers the error. It exists to prevent users from scheduling reports every second/minute and flooding the screenshot worker and email infrastructure.","triggerScenarios":"POST/PUT to /api/v1/report/ or /api/v1/alert/ with a crontab like '* * * * *' (every minute) while ALERT_REPORTS_MINIMAL_INTERVAL is set to 300 or higher. Any schedule whose simulated next executions include a gap smaller than the configured minimum, e.g. '*/2 * * * *' with a 360-second minimum.","commonSituations":"Operator raises ALERT_REPORTS_MINIMAL_INTERVAL to protect workers and pre-existing tighter schedules start failing validation; migrating schedules from another tool with minute-level cadence; testing with aggressive crontabs in a dev instance with a hardened config.","solutions":["Change the crontab so consecutive executions are at least minimum_interval apart (e.g. '*/5 * * * *' for a 300s minimum)","If your deployment can sustain the load, lower ALERT_REPORTS_MINIMAL_INTERVAL in superset_config.py","If the check should not apply (minimum_interval < 120), verify the config value actually reached the worker; a stale webserver/worker holds the old value","Simulate the schedule with croniter locally ('for _ in range(60): next(it)') to confirm the smallest gap before resubmitting"],"exampleFix":"# before\ncrontab = '* * * * *'  # every minute; fails when min interval is 300s\n\n# after\ncrontab = '*/5 * * * *'  # every 5 minutes; passes a 300s minimum","handlingStrategy":"validation","validationCode":"from croniter import croniter\nfrom datetime import datetime\n\ndef crontab_meets_minimum(crontab: str, minimum_interval: int) -> bool:\n    if minimum_interval < 120:\n        return True\n    it = croniter(crontab, datetime.utcnow())\n    prev = next(it)\n    for _ in range(60 if minimum_interval <= 3660 else 24):\n        nxt = next(it)\n        if (nxt - prev).total_seconds() < minimum_interval:\n            return False\n        prev = nxt\n    return True\n\nassert crontab_meets_minimum('*/5 * * * *', 300)","typeGuard":"def is_valid_schedule(crontab: str, minimum_interval: int) -> bool:\n    return croniter.is_valid(crontab) and crontab_meets_minimum(crontab, minimum_interval)","tryCatchPattern":"try:\n    CreateReportCommand(user, payload).run()\nexcept ReportScheduleFrequencyNotAllowed as ex:\n    # show minimum interval to user, request a sparser crontab\n    show_error(f'Schedule too frequent: minimum {ex.minimum_interval}s between runs')","preventionTips":["Mirror Superset's croniter gap-check client-side before submitting schedules","Keep ALERT_REPORTS_MINIMAL_INTERVAL documented in your internal scheduling guide","Never generate per-minute crontabs programmatically without checking the configured minimum"],"tags":["scheduling","cron","alerts-reports","configuration"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}