apache/superset · error · QueryObjectValidationError

Metric '%(metric)s' does not exist

Error message

Metric '%(metric)s' does not exist

What it means

QueryObjectValidationError raised in get_series_orderby_expression (models.py:2090) when series_limit_metric is neither an adhoc metric dict (is_adhoc_metric), nor a string matching a saved metric name in metrics_by_name. The series limit metric controls which metric drives row-order truncation (series_limit); it must resolve to one of the dataset's known metrics.

Source

Thrown at superset/connectors/sqla/models.py:2090

    def _get_series_orderby(
        self,
        series_limit_metric: Metric,
        metrics_by_name: dict[str, SqlMetric],
        columns_by_name: dict[str, TableColumn],
        template_processor: BaseTemplateProcessor | None = None,
    ) -> Column:
        if utils.is_adhoc_metric(series_limit_metric):
            assert isinstance(series_limit_metric, dict)
            ob = self.adhoc_metric_to_sqla(series_limit_metric, columns_by_name)
        elif (
            isinstance(series_limit_metric, str)
            and series_limit_metric in metrics_by_name
        ):
            ob = metrics_by_name[series_limit_metric].get_sqla_col(
                template_processor=template_processor
            )
        else:
            raise QueryObjectValidationError(
                _("Metric '%(metric)s' does not exist", metric=series_limit_metric)
            )
        return ob

    def _get_top_groups(
        self,
        df: pd.DataFrame,
        dimensions: list[str],
        groupby_exprs: dict[str, Any],
        columns_by_name: dict[str, TableColumn],
    ) -> ColumnElement:
        groups = []
        for _unused, row in df.iterrows():
            group = []
            for dimension in dimensions:
                value = self._normalize_prequery_result_type(
                    row,
                    dimension,

View on GitHub (pinned to f4587218dd)

Solutions

  1. Set series_limit_metric to a metric that exists on the dataset (exact name) or remove it to fall back to the default ordering metric.
  2. If the metric was renamed, update the dataset or re-save the chart so the reference matches.
  3. For adhoc form, ensure the dict passes is_adhoc_metric (has expressionType and required fields).

Example fix

// before
formData.series_limit_metric = 'sum___sales' // saved metric is 'Sales'

// after
formData.series_limit_metric = 'Sales'
Defensive patterns

Strategy: validation

Validate before calling

def validate_series_limit_metric(metric, metrics_by_name) -> None:
    if metric is None:
        return
    if isinstance(metric, str) and metric not in metrics_by_name:
        raise ValueError(f"series_limit_metric {metric!r} is not a saved metric on the dataset")
    if isinstance(metric, dict) and metric.get("expressionType") not in {"SIMPLE", "SQL"}:
        raise ValueError("series_limit_metric dict must be a valid adhoc metric")

Type guard

def resolves_to_known_metric(metric, metrics_by_name) -> bool:
    if isinstance(metric, str):
        return metric in metrics_by_name
    if isinstance(metric, dict):
        return metric.get("expressionType") in {"SIMPLE", "SQL"}
    return False

Try / catch

from superset.exceptions import QueryObjectValidationError

try:
    ob = table.get_series_orderby_expression(metric, columns_by_name, metrics_by_name)
except QueryObjectValidationError as ex:
    if "does not exist" in str(ex):
        metric = None  # fall back to default ordering
        ob = table.get_series_orderby_expression(metric, columns_by_name, metrics_by_name)
    else:
        raise

Prevention

When it happens

Trigger: Chart payload with series_limit_metric set to a metric name that is not saved on the dataset, or a dict that does not satisfy the adhoc-metric shape (e.g. missing expressionType). Emitted from queries that use series limiting (timeseries with row_limit per series).

Common situations: Metric renamed/deleted on the dataset while chart formData keeps the old series_limit_metric; dashboards imported from other instances referencing missing metrics; hand-written payloads with typos in the metric name.

Related errors


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