This is an automated email from the ASF dual-hosted git repository. eschutho pushed a commit to branch fix-extra-params-encrypted-extra-decode-error in repository https://gitbox.apache.org/repos/asf/superset.git
commit 36f620867a426ce1908d7ad6e6e409c934173a3b Author: Elizabeth Thompson <[email protected]> AuthorDate: Thu Sep 24 16:47:57 2026 +0000 fix(db_engine_specs): raise SupersetGenericDBErrorException instead of bare-reraising JSONDecodeError BaseEngineSpec.get_extra_params and update_params_from_encrypted_extra caught json.JSONDecodeError on malformed `extra` / `encrypted_extra`, logged it, and re-raised the raw simplejson exception. Wrap it in a SupersetGenericDBErrorException so callers that handle SupersetException return a typed error instead of an opaque 500. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- superset/db_engine_specs/base.py | 5 ++-- tests/unit_tests/db_engine_specs/test_base.py | 33 ++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/superset/db_engine_specs/base.py b/superset/db_engine_specs/base.py index a32aeb9f34d..2c253c66642 100644 --- a/superset/db_engine_specs/base.py +++ b/superset/db_engine_specs/base.py @@ -71,6 +71,7 @@ from superset.exceptions import ( OAuth2Error, OAuth2RedirectError, OAuth2TokenRefreshError, + SupersetGenericDBErrorException, SupersetParseError, ) from superset.key_value.types import JsonKeyValueCodec, KeyValueResource @@ -2727,7 +2728,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods extra = json.loads(database.extra) except json.JSONDecodeError as ex: logger.error(ex, exc_info=True) - raise + raise SupersetGenericDBErrorException(message=str(ex)) from ex return extra @staticmethod @@ -2748,7 +2749,7 @@ class BaseEngineSpec: # pylint: disable=too-many-public-methods params.update(encrypted_extra) except json.JSONDecodeError as ex: logger.error(ex, exc_info=True) - raise + raise SupersetGenericDBErrorException(message=str(ex)) from ex @classmethod def array_contains_any(cls, col: ColumnElement, values: list[Any]) -> ColumnElement: diff --git a/tests/unit_tests/db_engine_specs/test_base.py b/tests/unit_tests/db_engine_specs/test_base.py index 3bb258fb199..63d61c5f4c3 100644 --- a/tests/unit_tests/db_engine_specs/test_base.py +++ b/tests/unit_tests/db_engine_specs/test_base.py @@ -39,7 +39,11 @@ from superset.db_engine_specs.base import ( convert_inspector_columns, ) from superset.errors import ErrorLevel, SupersetError, SupersetErrorType -from superset.exceptions import OAuth2Error, OAuth2RedirectError +from superset.exceptions import ( + OAuth2Error, + OAuth2RedirectError, + SupersetGenericDBErrorException, +) from superset.sql.parse import Table from superset.superset_typing import ( OAuth2ClientConfig, @@ -345,6 +349,33 @@ def test_quote_table() -> None: ) +def test_get_extra_params_malformed_json(mocker: MockerFixture) -> None: + """ + Test that malformed JSON in `extra` raises a Superset exception instead of + leaking the raw `JSONDecodeError`. + """ + database = mocker.MagicMock(extra="{not valid json") + + with pytest.raises(SupersetGenericDBErrorException): + BaseEngineSpec.get_extra_params(database) + + +def test_update_params_from_encrypted_extra_malformed_json( + mocker: MockerFixture, +) -> None: + """ + Test that malformed JSON in `encrypted_extra` raises a Superset exception + instead of leaking the raw `JSONDecodeError`. + """ + database = mocker.MagicMock(encrypted_extra="{not valid json") + params: dict[str, Any] = {} + + with pytest.raises(SupersetGenericDBErrorException): + BaseEngineSpec.update_params_from_encrypted_extra(database, params) + + assert params == {} + + def test_mask_encrypted_extra() -> None: """ Test that the private key is masked when the database is edited.
