This is an automated email from the ASF dual-hosted git repository. eschutho pushed a commit to branch fix-sqllab-format-template-params-non-dict in repository https://gitbox.apache.org/repos/asf/superset.git
commit 15a586baf2245536f9e26bb6c3c9a48f677f8a51 Author: Elizabeth Thompson <[email protected]> AuthorDate: Wed Sep 30 16:37:28 2026 +0000 fix(sqllab): ignore non-object template_params in format_sql instead of 500 When template_params is valid JSON but not an object (e.g. an array, number, string, or boolean), the ** unpacking in process_template raises a TypeError that propagates as an unhandled 500. Treat non-dict values the same as invalid JSON: log a warning and skip Jinja processing. Co-Authored-By: Claude Opus 4.6 <[email protected]> --- superset/sqllab/api.py | 7 ++++++ tests/unit_tests/sqllab/api_test.py | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/superset/sqllab/api.py b/superset/sqllab/api.py index e8f4362a711..21a49feb149 100644 --- a/superset/sqllab/api.py +++ b/superset/sqllab/api.py @@ -257,6 +257,13 @@ class SqlLabRestApi(BaseSupersetApi): if isinstance(template_params, str) else template_params ) + if not isinstance(template_params, dict): + logger.warning( + "template_params is not a dict: %s." + " Skipping processing", + type(template_params).__name__, + ) + template_params = None if template_params: # Check access before rendering the Jinja # template (mirrors the SQL Lab execute path). diff --git a/tests/unit_tests/sqllab/api_test.py b/tests/unit_tests/sqllab/api_test.py index fc739748e61..00517326329 100644 --- a/tests/unit_tests/sqllab/api_test.py +++ b/tests/unit_tests/sqllab/api_test.py @@ -20,6 +20,7 @@ import re from typing import Any from unittest.mock import MagicMock, patch +import pytest from flask import Flask from pytest_mock import MockerFixture @@ -108,3 +109,47 @@ def test_format_sql_checks_access_before_rendering( assert response.status_code == 403 raise_for_access.assert_called_once() get_template_processor.assert_not_called() + + [email protected]( + "template_params", + [ + "[1, 2]", + "5", + '"abc"', + "true", + "null", + ], +) +def test_format_sql_non_dict_template_params( + mocker: MockerFixture, + client: Any, + full_api_access: None, + template_params: str, +) -> None: + """Non-dict JSON template_params must not cause a 500 TypeError.""" + database = mocker.MagicMock() + database.db_engine_spec.engine = "presto" + mocker.patch( + "superset.sqllab.api.DatabaseDAO.find_by_id", + return_value=database, + ) + raise_for_access = mocker.patch( + "superset.sqllab.api.security_manager.raise_for_access", + ) + get_template_processor = mocker.patch( + "superset.sqllab.api.get_template_processor", + ) + + response = client.post( + "/api/v1/sqllab/format_sql/", + json={ + "sql": "SELECT 1", + "database_id": 1, + "template_params": template_params, + }, + ) + + assert response.status_code == 200 + raise_for_access.assert_not_called() + get_template_processor.assert_not_called()
