apache/superset · error · ReportScheduleForbiddenError
Changing this report is forbidden
Error message
Changing this report is forbidden
What it means
ReportScheduleForbiddenError from DeleteReportCommand.validate: for each loaded model the command calls security_manager.raise_for_editorship(model), and a raised SupersetSecurityException is wrapped as 'Changing this report is forbidden'. Only owners (or admins) may delete a report schedule.
Source
Thrown at superset/commands/report/delete.py:58
@transaction(on_error=partial(on_error, reraise=ReportScheduleDeleteFailedError))
def run(self) -> None:
self.validate()
assert self._models
ReportScheduleDAO.delete(self._models)
def validate(self) -> None:
# Validate/populate model exists
self._models = ReportScheduleDAO.find_by_ids(self._model_ids)
if not self._models or len(self._models) != len(self._model_ids):
raise ReportScheduleNotFoundError()
# Check editorship
for model in self._models:
try:
security_manager.raise_for_editorship(model)
except SupersetSecurityException as ex:
raise ReportScheduleForbiddenError() from ex
View on GitHub (pinned to f4587218dd)
Solutions
- Have an admin (or the current owner) perform the delete, or add the caller to the report's owners first
- For service-account automation, create reports with that account as owner from the start
- Batch deletes should be pre-filtered to rows the caller owns
Example fix
# before
DeleteReportCommand(current_user, [report_id]).run() # not an owner -> 403
# after
# admin adds the caller as owner, then:
UpdateReportCommand(admin, report_id, {'owners': [*old_owners, current_user.id]}).run()
DeleteReportCommand(current_user, [report_id]).run() Defensive patterns
Strategy: validation
Validate before calling
from superset import security_manager
for rid in report_ids:
model = ReportScheduleDAO.find_by_id(rid)
if model and not security_manager.is_owner(model):
raise PermissionError(f'not an owner of report {rid}') # fail before the command Try / catch
try:
DeleteReportCommand(user, ids).run()
except ReportScheduleForbiddenError:
# route to an admin, or add caller to owners first
... Prevention
- Create reports with the service account that will manage them as an owner
- Batch deletes should be pre-filtered to owned rows
- When owners leave, transfer ownership before deactivating their accounts
When it happens
Trigger: DELETE /api/v1/report/{id} by a user who is not in the report's owners list and lacks admin rights. Mixed batches where the caller owns some but not all targeted reports also fail on the first non-owned model.
Common situations: A teammate left and their reports are orphaned; scripts run as a service account that never owned the schedules; role has can_delete on ReportSchedule but the object-level owner check still denies.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- There are associated alerts or reports: %(report_names)s
- Changing this Dashboard is forbidden
- Changing this dataset is forbidden.
- Changing this dataset is forbidden
- You don't have access to this dataset.
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/2620b8987132be13.
Report an issue: GitHub.