apache/superset · error · ReportScheduleInvalidError

Report Schedule parameters are invalid.

Error message

Report Schedule parameters are invalid.

What it means

ReportScheduleInvalidError(exceptions=[...]) aggregates all ValidationErrors from ReportScheduleUpdateCommand.validate. The shown branch fires when send_failed_reports is true but retry_on_failure is disabled (falling back to the stored DB value when absent from the payload), or when the schedule is an ALERT with retry_on_failure enabled.

Source

Thrown at superset/commands/report/update.py:215

        # Fall back to the existing DB value for fields not in the payload.
        send_failed = self._properties.get(
            "send_failed_reports", self._model.send_failed_reports
        )
        retry_enabled = self._properties.get(
            "retry_on_failure", self._model.retry_on_failure
        )
        if send_failed and not retry_enabled:
            msg = _("send_failed_reports requires retry_on_failure to be enabled")
            exceptions.append(ValidationError({"send_failed_reports": [msg]}))

        # Retries are only supported for reports, not alerts.
        report_type = self._properties.get("type", self._model.type)
        if report_type == ReportScheduleType.ALERT and retry_enabled:
            msg = _("Retries are not supported for alerts")
            exceptions.append(ValidationError({"retry_on_failure": [msg]}))

        if exceptions:
            raise ReportScheduleInvalidError(exceptions=exceptions)

View on GitHub (pinned to f4587218dd)

Solutions

  1. Include 'retry_on_failure': true in the same PUT payload whenever send_failed_reports is true
  2. For alerts, set both retry_on_failure and send_failed_reports to false (retries only apply to reports)
  3. Inspect the response's validation error map (keys send_failed_reports / retry_on_failure) to see which constraint tripped

Example fix

# before
client.put(f'/api/v1/report/{rid}', json={'send_failed_reports': True})

# after
client.put(f'/api/v1/report/{rid}', json={'send_failed_reports': True, 'retry_on_failure': True})
Defensive patterns

Strategy: validation

Validate before calling

retry_on = props.get('retry_on_failure', current.get('retry_on_failure', False))
send_failed = props.get('send_failed_reports', current.get('send_failed_reports', False))
rtype = props.get('type', current.get('type'))
assert not (send_failed and not retry_on), 'retry_on_failure required'
assert not (rtype == 'Alert' and retry_on), 'alerts cannot retry'

Type guard

def retry_payload_is_consistent(props: dict, stored: dict) -> bool:
    retry_on = props.get('retry_on_failure', stored.get('retry_on_failure', False))
    send_failed = props.get('send_failed_reports', stored.get('send_failed_reports', False))
    rtype = props.get('type', stored.get('type'))
    return (not send_failed or retry_on) and not (rtype == 'Alert' and retry_on)

Try / catch

from superset.commands.report.exceptions import ReportScheduleInvalidError
try:
    ReportScheduleUpdateCommand(rid, props).run()
except ReportScheduleInvalidError as e:
    field_errors = e.exceptions  # map of field -> messages; fix and resubmit

Prevention

When it happens

Trigger: PUT /api/v1/report/{id} with {'send_failed_reports': true} while retry_on_failure is false/omitted; or with type='Alert' (ReportScheduleType.ALERT) together with retry_on_failure=true; the retry fields fall back to existing DB values so a previously stored retry config can also trip the alert-type check.

Common situations: Partial update that sets only send_failed_reports on a schedule stored with retries disabled; converting a report with retries enabled into an alert without clearing retry_on_failure; API clients copying full payloads between report and alert schedules.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/a75df4363176db14. Report an issue: GitHub.