apache/superset · error · ReportScheduleUnexpectedError
Report schedule ( ) has no resolvable target (chart_id= …
Error message
Report schedule {id} ({name!r}) has no resolvable target (chart_id={chart_id}, dashboard_id={dashboard_id}); the report has neither a chart nor a dashboard. What it means
ReportScheduleUnexpectedError raised as a defensive fallback in _get_url when both chart and dashboard relationships are None AND neither chart_id nor dashboard_id is set — i.e. a malformed report row with no target at all. The message embeds the schedule id, name, and both null target ids so operators can identify the row directly.
Solutions
- Inspect the row named in the message: SELECT * FROM report_schedule WHERE id = <id>
- Fix the row by setting a valid chart_id or dashboard_id, or delete the malformed schedule
- If a custom tool created this row, fix the tool to always set exactly one target
Example fix
-- before: malformed row UPDATE report_schedule SET chart_id = NULL WHERE id = 42; -- later execution fails -- after UPDATE report_schedule SET chart_id = 123 WHERE id = 42; -- valid target
Defensive patterns
Strategy: validation
Validate before calling
def report_has_target(report) -> bool:
return report.chart_id is not None or report.dashboard_id is not None Type guard
def is_well_formed_report(report_schedule) -> bool:
"""A report must carry exactly one non-null target id."""
return (report_schedule.chart_id is not None) ^ (report_schedule.dashboard_id is not None) Try / catch
try:
_get_url()
except ReportScheduleUnexpectedError as ex:
if 'no resolvable target' in str(ex):
# quarantine the malformed row named in the message
flag_for_repair(report_schedule.id) Prevention
- Never insert report_schedule rows by hand without exactly one target id
- Add a DB constraint or CI check that chart_id/dashboard_id are not both null
- Use the API for all report creation so validation always runs
When it happens
Trigger: A report_schedule row manually inserted (or corrupted) with chart_id and dashboard_id both NULL; bugs in import/export flows that strip target ids; direct DB edits. Normal API paths cannot create a target-less report.
Common situations: Migrations or manual SQL backfills that leave nulls; a partially applied update that cleared the target column; test fixtures created without targets.
Related errors
- Chart has no valid query context saved.
- Failed taking a screenshot
- Screenshot failed; aborting to avoid sending a partial…
- The chart this report targets was deleted. Restore the…
- The dashboard this report targets was deleted. Restore the…
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/b2f84fddf2bb9ada.
Report an issue: GitHub.
Appendix: source
Thrown at superset/commands/report/execute.py:509
# opaquely; raising here surfaces a clear, actionable error inside
# the state-machine envelope (ERROR log row + notification dispatch).
# Every content path (_get_screenshots, _get_csv_data,
# _get_embedded_data, _get_notification_content) funnels through this
# method, so this is the single choke point.
if chart is None and dashboard is None:
if self._report_schedule.chart_id is not None:
raise ReportScheduleTargetChartDeletedError()
# Symmetric guard for dashboard targets. Dashboard soft delete lands
# in the sibling rollout; until then this cannot fire (a dashboard
# with dependent reports cannot be deleted), which makes it inert
# rather than wrong — and it keeps the report-target error vocabulary
# parallel across entities from day one.
if self._report_schedule.dashboard_id is not None:
raise ReportScheduleTargetDashboardDeletedError()
# Defensive fallback for a malformed report with no target IDs.
# Missing relationships with a target ID are handled by the
# dedicated deleted-target errors above.
raise ReportScheduleUnexpectedError(
f"Report schedule {self._report_schedule.id} "
f"({self._report_schedule.name!r}) has no resolvable target "
f"(chart_id={self._report_schedule.chart_id}, "
f"dashboard_id={self._report_schedule.dashboard_id}); "
"the report has neither a chart nor a dashboard."
)
force = "true" if self._report_schedule.force_screenshot else "false"
if chart:
if result_format in {
ChartDataResultFormat.CSV,
ChartDataResultFormat.XLSX,
ChartDataResultFormat.JSON,
ChartDataResultFormat.XLSX,
}:
return get_url_path(
"ChartDataRestApi.get_data",
pk=self._report_schedule.chart_id,View on GitHub (pinned to f4587218dd)