You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2026/08/06 22:05:14 UTC

(superset) branch master updated: fix(datasets): catch TemplateError instead of narrower TemplateSyntaxError in render_dataset_fields (#42802)

This is an automated email from the ASF dual-hosted git repository.

eschutho pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 7dd6ce835f5 fix(datasets): catch TemplateError instead of narrower TemplateSyntaxError in render_dataset_fields (#42802)
7dd6ce835f5 is described below

commit 7dd6ce835f5652d790fd8fc5c1900680f050365b
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Thu Aug 6 15:05:08 2026 -0700

    fix(datasets): catch TemplateError instead of narrower TemplateSyntaxError in render_dataset_fields (#42802)
---
 superset/datasets/api.py               |  4 +--
 tests/unit_tests/datasets/api_tests.py | 51 ++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/superset/datasets/api.py b/superset/datasets/api.py
index a35e22345ae..1fc7634b8b3 100644
--- a/superset/datasets/api.py
+++ b/superset/datasets/api.py
@@ -30,7 +30,7 @@ from flask_appbuilder.api.schemas import get_item_schema
 from flask_appbuilder.const import API_RESULT_RES_KEY, API_SELECT_COLUMNS_RIS_KEY
 from flask_appbuilder.models.sqla.interface import SQLAInterface
 from flask_babel import ngettext
-from jinja2.exceptions import TemplateSyntaxError
+from jinja2.exceptions import TemplateError
 from marshmallow import ValidationError
 from sqlalchemy.orm.exc import MultipleResultsFound
 
@@ -1835,7 +1835,7 @@ class DatasetRestApi(SoftDeleteApiMixin, BaseSupersetModelRestApi):
 
             try:
                 data[new_key] = func(data[key])
-            except (TemplateSyntaxError, SupersetSyntaxErrorException) as ex:
+            except (TemplateError, SupersetSyntaxErrorException) as ex:
                 template_exception = SupersetTemplateException(
                     f"Unable to render expression from dataset {item_type}.",
                 )
diff --git a/tests/unit_tests/datasets/api_tests.py b/tests/unit_tests/datasets/api_tests.py
index c536fad9ea5..c2d4b0711cf 100644
--- a/tests/unit_tests/datasets/api_tests.py
+++ b/tests/unit_tests/datasets/api_tests.py
@@ -122,6 +122,57 @@ def test_get_dataset_include_rendered_sql_passes_table_to_template_processor(
     mock_get_processor.assert_called_once_with(database=database, table=dataset)
 
 
+def test_get_dataset_include_rendered_sql_handles_undefined_error(
+    session: Session,
+    client: Any,
+    full_api_access: None,
+) -> None:
+    """
+    Dataset API: Test that include_rendered_sql returns a typed 422 instead
+    of an unhandled 500 when the template processor raises a raw
+    ``jinja2.exceptions.UndefinedError``.
+
+    Regression test for the bug where an undefined variable accessed via
+    attribute/subscript (e.g. ``{{ foo.bar }}``) raises ``UndefinedError``
+    from ``process_template``, which is not a subclass of
+    ``TemplateSyntaxError`` and so escaped ``render_dataset_fields``'s
+    exception handling unhandled.
+    """
+    from jinja2.exceptions import UndefinedError
+
+    from superset.connectors.sqla.models import SqlaTable
+    from superset.models.core import Database
+
+    SqlaTable.metadata.create_all(db.session.get_bind())
+
+    database = Database(
+        database_name="my_db",
+        sqlalchemy_uri="sqlite://",
+    )
+    dataset = SqlaTable(
+        table_name="test_render_sql_undefined_table",
+        schema="my_schema",
+        database=database,
+        sql="SELECT 1",
+    )
+    db.session.add(dataset)
+    db.session.flush()
+
+    mock_processor = MagicMock()
+    mock_processor.process_template.side_effect = UndefinedError("'foo' is undefined")
+
+    with patch(
+        "superset.datasets.api.get_template_processor",
+        return_value=mock_processor,
+    ):
+        response = client.get(
+            f"/api/v1/dataset/{dataset.id}?include_rendered_sql=true",
+        )
+
+    assert response.status_code == 422
+    assert "Unable to render expression from dataset" in response.json["message"]
+
+
 def test_handle_filters_args_returns_request_scoped_filters(
     session: Session,
     client: Any,