apache/superset · error · QueryObjectValidationError
Error in jinja expression in metric expression: %(msg)s
Error message
Error in jinja expression in metric expression: %(msg)s
What it means
QueryObjectValidationError raised in SqlMetric.get_sqla_col (models.py:1383) when Jinja processing of a saved metric's SQL expression throws SupersetSyntaxErrorException. Metrics stored on the dataset (as opposed to adhoc metrics) can contain Jinja; the expression is rendered before being turned into a literal_column in the query.
Source
Thrown at superset/connectors/sqla/models.py:1383
self.table.database,
self.table.catalog,
self.table.schema,
self.table.db_engine_spec.engine,
)
def get_sqla_col(
self,
label: str | None = None,
template_processor: BaseTemplateProcessor | None = None,
) -> Column:
label = label or self.metric_name
expression = self.expression
if template_processor:
try:
expression = template_processor.process_template(expression)
except SupersetSyntaxErrorException as ex:
msg = str(ex)
raise QueryObjectValidationError(
_(
"Error in jinja expression in metric expression: %(msg)s",
msg=msg,
)
) from ex
if expression != self.expression:
# Re-check the rendered expression before embedding it.
expression = validate_rendered_expression(
expression,
self.table.database,
self.table.catalog,
self.table.schema,
)
if expression:
expression = self._validate_stored_expression(expression)
sqla_col: ColumnClause = literal_column(expression)
return self.table.database.make_sqla_column_compatible(sqla_col, label)View on GitHub (pinned to f4587218dd)
Solutions
- Edit the metric in the dataset editor and fix/guard the Jinja (|default for filter_values, remove undefined macros).
- Read %(msg)s — it pinpoints which part of the template failed.
- If Jinja is unnecessary for the metric, replace with plain SQL so rendering cannot fail.
- For context-dependent metrics, prefer two variants: one plain for scheduled artifacts, one templated for interactive use.
Example fix
-- before (metric SQL expression)
SUM({{ filter_values('amount_col')[0] }})
-- after
SUM({{ filter_values('amount_col') | default(['amount'], true) | first }}) Defensive patterns
Strategy: try-catch
Validate before calling
from jinja2.sandbox import SandboxedEnvironment
def metric_expression_renders(expression: str) -> bool:
try:
SandboxedEnvironment().from_string(expression).render({})
return True
except Exception:
return False Try / catch
from superset.exceptions import QueryObjectValidationError
try:
metric_col = sql_metric.get_sqla_col(template_processor=processor)
except QueryObjectValidationError as ex:
if "metric expression" in str(ex):
flag_stored_metric(sql_metric.metric_name, ex)
raise Prevention
- Prefer plain SQL in stored metrics; use Jinja only when the value must be context-dependent.
- Default-guard filter_values-based metric Jinja.
- Smoke-test all dataset metrics with an empty filter context after authoring.
When it happens
Trigger: A dataset metric whose expression embeds Jinja (e.g. SUM({{ column_for_total }}) or filter_values-dependent logic) that fails at render time — undefined macro, syntax error, or sandbox restriction — when any chart aggregates that metric.
Common situations: Metric Jinja authored for interactive dashboards breaking under reports/alerts/thumbnails where runtime filter context is missing; typos in macros; upgrade tightening the sandbox so previously-rendering filters now raise.
Related errors
- Dataset metric not found.
- Error in jinja expression in column expression: %(msg)s
- Error in jinja expression in datetime column: %(msg)s
- Changing this dataset is forbidden.
- Error in jinja expression in RLS filters: %(msg)s
AI-assisted analysis of apache/superset@f4587218dd (2026-08-14).
Data as JSON: /api/errors/e09683802a799826.
Report an issue: GitHub.