apache/superset · error · DashboardNotFoundError

Dashboard not found.

Error message

Dashboard not found.

What it means

DashboardNotFoundError raised by DashboardDAO.get_by_id_or_slug(): the lookup by id-or-slug (id_or_slug_filter) plus the DAO base filter returned one_or_none() == None. As with charts, the base filter means 'not found' conflates 'does not exist' with 'not visible to you'. This variant follows the outerjoin(editors) path.

Source

Thrown at superset/daos/dashboard.py:195

    @classmethod
    def get_by_id_or_slug(cls, id_or_slug: int | str) -> Dashboard:
        if is_uuid(id_or_slug):
            # just get dashboard if it's uuid
            dashboard = Dashboard.get(id_or_slug)
        else:
            query = (
                db.session.query(Dashboard)
                .filter(id_or_slug_filter(id_or_slug))
                .outerjoin(Dashboard.editors)
            )
            # Apply dashboard base filters
            query = cls.base_filter("id", SQLAInterface(Dashboard, db.session)).apply(
                query, None
            )
            dashboard = query.one_or_none()
        if not dashboard:
            raise DashboardNotFoundError()

        # make sure we still have basic access check from security manager
        try:
            dashboard.raise_for_access()
        except SupersetSecurityException as ex:
            raise DashboardAccessDeniedError() from ex

        return dashboard

    @staticmethod
    def get_datasets_for_dashboard(id_or_slug: str) -> list[tuple[Any, dict[str, Any]]]:
        dashboard = DashboardDAO.get_by_id_or_slug(id_or_slug)
        return dashboard.datasets_trimmed_for_slices()

    @staticmethod
    def get_tabs_for_dashboard(id_or_slug: str) -> dict[str, Any]:
        dashboard = DashboardDAO.get_by_id_or_slug(id_or_slug)
        return dashboard.tabs

View on GitHub (pinned to f4587218dd)

Solutions

  1. List dashboards as the same user (GET /api/v1/dashboard/) to confirm existence, the current slug, and visibility.
  2. Prefer the stable dashboard UUID over id or slug in integrations.
  3. Fix access: set the dashboard's ownership/roles or grant the role can-read access if the row is simply filtered out.
  4. Update the stored slug reference after renames.

Example fix

# before
DashboardDAO.get_by_id_or_slug("q2-sales")  # slug renamed to 'sales-q2'

# after
# resolve via the API filter on the immutable uuid
GET /api/v1/dashboard/?q={"filter":[{"col":"uuid","opr":"eq","value":"<uuid>"}]}
Defensive patterns

Strategy: try-catch

Validate before calling

def dashboard_exists_and_visible(id_or_slug: str) -> bool:
    try:
        DashboardDAO.get_by_id_or_slug(id_or_slug)
        return True
    except (DashboardNotFoundError, DashboardAccessDeniedError):
        return False

Type guard

def is_dashboard_slug(s: str) -> bool:
    return isinstance(s, str) and bool(s) and not s.isdigit()  # digit strings are ids

Try / catch

try:
    dash = DashboardDAO.get_by_id_or_slug(id_or_slug)
except DashboardNotFoundError:
    abort(404)
except DashboardAccessDeniedError:
    abort(403)

Prevention

When it happens

Trigger: GET /api/v1/dashboard/<id-or-slug> where the dashboard was deleted, the slug changed (slug is mutable via json metadata), or the current user lacks read access; malformed id/slug string.

Common situations: Hardcoded dashboard slugs that break when someone edits the dashboard title/slug; stale ids after environment re-imports; embedded-SDK integrations referencing a dashboard the service account can't see.

Related errors


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