apache/superset · error · DashboardUpdateFailedError

Dashboard not found

Error message

Dashboard not found

What it means

DashboardUpdateFailedError('Dashboard not found') raised by DashboardDAO.update_native_filters_config when called with dashboard=None (the function's guard for a missing dashboard argument). It is a control-flow guard inside native-filter reordering/deletion handling, not a query result — the caller passed no dashboard object.

Source

Thrown at superset/daos/dashboard.py:569

        native_filter_configuration = metadata.get("native_filter_configuration", [])

        tab_filters = defaultdict(list)
        for filter in native_filter_configuration:
            if tabs_in_scope := filter.get("tabsInScope", []):
                for tab_key in tabs_in_scope:
                    tab_filters[tab_key].append(filter)
            tab_filters["all"].append(filter)

        return tab_filters

    @classmethod
    def update_native_filters_config(
        cls,
        dashboard: Dashboard | None = None,
        attributes: dict[str, Any] | None = None,
    ) -> list[dict[str, Any]]:
        if not dashboard:
            raise DashboardUpdateFailedError("Dashboard not found")

        if attributes:
            try:
                _parsed = json.loads(dashboard.json_metadata or "{}")
            except (json.JSONDecodeError, TypeError):
                _parsed = {}
            metadata = _parsed if isinstance(_parsed, dict) else {}
            native_filter_configuration = metadata.get(
                "native_filter_configuration", []
            )
            reordered_filter_ids: list[int] = attributes.get("reordered", [])
            deleted_ids = set(attributes.get("deleted", []))
            modified_map = {f.get("id"): f for f in attributes.get("modified", [])}
            updated_configuration = []

            # Modify / Delete existing filters
            for conf in native_filter_configuration:
                conf_id = conf.get("id")

View on GitHub (pinned to f4587218dd)

Solutions

  1. Resolve the Dashboard first: dash = DashboardDAO.get_by_id_or_slug(id_or_slug), handling its NotFound/AccessDenied errors, then pass it in.
  2. Do not forward None from upstream callers — fail at the fetch site.
  3. Catch DashboardUpdateFailedError in the API layer and map it to 404 for the client.

Example fix

# before
DashboardDAO.update_native_filters_config(None, {"reordered": [2, 1]})

# after
dash = DashboardDAO.get_by_id_or_slug(id_or_slug)  # raises its own errors if absent
DashboardDAO.update_native_filters_config(dash, {"reordered": [2, 1]})
Defensive patterns

Strategy: type-guard

Validate before calling

def has_dashboard_arg(dashboard) -> bool:
    return dashboard is not None

Type guard

def is_resolved_dashboard(obj) -> bool:
    from superset.models.dashboard import Dashboard
    return isinstance(obj, Dashboard) and obj.id is not None

Try / catch

try:
    DashboardDAO.update_native_filters_config(dash, attributes)
except DashboardUpdateFailedError as ex:
    if 'not found' in str(ex):
        abort(404)
    raise

Prevention

When it happens

Trigger: Internal/extension code invoking update_native_filters_config(dashboard=None, attributes={...}) — e.g. a dashboard API path where the dashboard failed to load upstream and None was forwarded instead of raising earlier.

Common situations: Custom plugins or fork code calling the DAO method directly without resolving the Dashboard first; refactors that moved dashboard fetching but kept the None default.

Related errors


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