{"record":{"id":"a75df4363176db14","repo":"apache/superset","slug":"report-schedule-parameters-are-invalid-a75df4","errorCode":null,"errorMessage":"Report Schedule parameters are invalid.","messagePattern":"Report Schedule parameters are invalid\\.","errorType":"validation","errorClass":"ReportScheduleInvalidError","httpStatus":422,"severity":"error","filePath":"superset/commands/report/update.py","lineNumber":215,"sourceCode":"        # Fall back to the existing DB value for fields not in the payload.\n        send_failed = self._properties.get(\n            \"send_failed_reports\", self._model.send_failed_reports\n        )\n        retry_enabled = self._properties.get(\n            \"retry_on_failure\", self._model.retry_on_failure\n        )\n        if send_failed and not retry_enabled:\n            msg = _(\"send_failed_reports requires retry_on_failure to be enabled\")\n            exceptions.append(ValidationError({\"send_failed_reports\": [msg]}))\n\n        # Retries are only supported for reports, not alerts.\n        report_type = self._properties.get(\"type\", self._model.type)\n        if report_type == ReportScheduleType.ALERT and retry_enabled:\n            msg = _(\"Retries are not supported for alerts\")\n            exceptions.append(ValidationError({\"retry_on_failure\": [msg]}))\n\n        if exceptions:\n            raise ReportScheduleInvalidError(exceptions=exceptions)\n","sourceCodeStart":197,"sourceCodeEnd":216,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/report/update.py#L197-L216","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Include 'retry_on_failure': true in the same PUT payload whenever send_failed_reports is true","For alerts, set both retry_on_failure and send_failed_reports to false (retries only apply to reports)","Inspect the response's validation error map (keys send_failed_reports / retry_on_failure) to see which constraint tripped"],"exampleFix":"# before\nclient.put(f'/api/v1/report/{rid}', json={'send_failed_reports': True})\n\n# after\nclient.put(f'/api/v1/report/{rid}', json={'send_failed_reports': True, 'retry_on_failure': True})","handlingStrategy":"validation","validationCode":"retry_on = props.get('retry_on_failure', current.get('retry_on_failure', False))\nsend_failed = props.get('send_failed_reports', current.get('send_failed_reports', False))\nrtype = props.get('type', current.get('type'))\nassert not (send_failed and not retry_on), 'retry_on_failure required'\nassert not (rtype == 'Alert' and retry_on), 'alerts cannot retry'","typeGuard":"def retry_payload_is_consistent(props: dict, stored: dict) -> bool:\n    retry_on = props.get('retry_on_failure', stored.get('retry_on_failure', False))\n    send_failed = props.get('send_failed_reports', stored.get('send_failed_reports', False))\n    rtype = props.get('type', stored.get('type'))\n    return (not send_failed or retry_on) and not (rtype == 'Alert' and retry_on)","tryCatchPattern":"from superset.commands.report.exceptions import ReportScheduleInvalidError\ntry:\n    ReportScheduleUpdateCommand(rid, props).run()\nexcept ReportScheduleInvalidError as e:\n    field_errors = e.exceptions  # map of field -> messages; fix and resubmit","preventionTips":["Always send retry_on_failure alongside send_failed_reports","Clear retry fields when converting a report to an alert","Log and read the per-field validation map instead of retrying the same payload"],"tags":["reports","validation","retry-config","alerts"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}