{"record":{"id":"4441358e734fba47","repo":"apache/superset","slug":"ssh-tunneling-is-not-enabled","errorCode":null,"errorMessage":"SSH Tunneling is not enabled","messagePattern":"SSH Tunneling is not enabled","errorType":"exception","errorClass":"SSHTunnelingNotEnabledError","httpStatus":400,"severity":"error","filePath":"superset/daos/database.py","lineNumber":73,"sourceCode":"\n    @classmethod\n    def create(\n        cls,\n        item: Database | None = None,\n        attributes: dict[str, Any] | None = None,\n    ) -> Database:\n        \"\"\"\n        Create a new database, with an optional SSH tunnel.\n        \"\"\"\n        ssh_tunnel_attributes = (\n            attributes.pop(\"ssh_tunnel\", None) if attributes else None\n        )\n\n        database = super().create(item, attributes)\n\n        if ssh_tunnel_attributes:\n            if not is_feature_enabled(\"SSH_TUNNELING\"):\n                raise SSHTunnelingNotEnabledError()\n\n            database.ssh_tunnel = SSHTunnel(**ssh_tunnel_attributes)\n\n        return database\n\n    @classmethod\n    def find_by_id(\n        cls,\n        model_id: str | int,\n        skip_base_filter: bool = False,\n        id_column: str | None = None,\n        query_options: list[Any] | None = None,\n        *,\n        skip_visibility_filter: bool = False,\n    ) -> Database | None:\n        \"\"\"\n        Find a database by id, eagerly loading the SSH tunnel relationship.\n        \"\"\"","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/daos/database.py#L55-L91","documentation":"SSHTunnelingNotEnabledError raised by DatabaseDAO.create when attributes contain an 'ssh_tunnel' block but the FEATURE_FLAGS['SSH_TUNNELING'] feature flag is disabled. The database row is created first (super().create) and the tunnel attribute is only then rejected, so the tunnel is silently absent while the error surfaces.","triggerScenarios":"POST /api/v1/database/ with payload including ssh_tunnel parameters while config FEATURE_FLAG['SSH_TUNNELING'] is unset/False (default off).","commonSituations":"Environments where the flag was never turned on in superset_config.py; fresh installs assuming tunnel support is on by default; CI configs copying a minimal config that drops feature flags.","solutions":["Enable the flag in superset_config.py: FEATURE_FLAG = {\"SSH_TUNNELING\": True} (also ensure sshtunnel Python deps are installed), then restart and re-send the ssh_tunnel attributes.","Or drop the ssh_tunnel block and connect directly.","If the database row was already created without a tunnel, update it with the tunnel after enabling the flag."],"exampleFix":"# before (superset_config.py)\nFEATURE_FLAG = {}\n\n# after\nFEATURE_FLAG = {\n    \"SSH_TUNNELING\": True,\n}","handlingStrategy":"validation","validationCode":"from superset.extensions import feature_flag_manager\n\ndef tunneling_enabled() -> bool:\n    from superset.utils.feature_flag_manager import is_feature_enabled\n    return bool(is_feature_enabled(\"SSH_TUNNELING\"))","typeGuard":"def payload_allows_tunnel(payload: dict) -> bool:\n    return \"ssh_tunnel\" not in (payload or {}) or is_feature_enabled(\"SSH_TUNNELING\")","tryCatchPattern":"try:\n    DatabaseDAO.create(item, attributes)\nexcept SSHTunnelingNotEnabledError:\n    # config defect, not transient: enable flag or drop the tunnel block\n    raise","preventionTips":["Set FEATURE_FLAG['SSH_TUNNELING'] = True in superset_config.py before any tunnel-backed database creation.","Install the sshtunnel extra when the flag is on.","Config-check feature flags in deployment smoke tests."],"tags":["database","ssh-tunnel","feature-flag","configuration"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}