{"record":{"id":"b5769897533a40e3","repo":"getredash/redash","slug":"ssh-tunneling-is-not-implemented-for-this-query-ru","errorCode":null,"errorMessage":"SSH tunneling is not implemented for this query runner yet.","messagePattern":"SSH tunneling is not implemented for this query runner yet\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"redash/query_runner/__init__.py","lineNumber":498,"sourceCode":"        return TYPE_BOOLEAN\n\n    try:\n        parser.parse(string_value)\n        return TYPE_DATETIME\n    except (ValueError, OverflowError):\n        pass\n\n    return TYPE_STRING\n\n\ndef with_ssh_tunnel(query_runner, details):\n    def tunnel(f):\n        @wraps(f)\n        def wrapper(*args, **kwargs):\n            try:\n                remote_host, remote_port = query_runner.host, query_runner.port\n            except NotImplementedError:\n                raise NotImplementedError(\"SSH tunneling is not implemented for this query runner yet.\")\n\n            stack = ExitStack()\n            try:\n                bastion_address = (details[\"ssh_host\"], details.get(\"ssh_port\", 22))\n                remote_address = (remote_host, remote_port)\n                auth = {\n                    \"ssh_username\": details[\"ssh_username\"],\n                    **settings.dynamic_settings.ssh_tunnel_auth(),\n                }\n                server = stack.enter_context(open_tunnel(bastion_address, remote_bind_address=remote_address, **auth))\n            except Exception as error:\n                raise type(error)(\"SSH tunnel: {}\".format(str(error)))\n\n            with stack:\n                try:\n                    query_runner.host, query_runner.port = server.local_bind_address\n                    result = f(*args, **kwargs)\n                finally:","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/query_runner/__init__.py#L480-L516","documentation":"The @tunnel decorator raises NotImplementedError when accessing query_runner.host or query_runner.port itself raised NotImplementedError — the runner doesn't expose host/port, so an SSH bastion tunnel cannot be constructed for it.","triggerScenarios":"Enabling 'Use SSH tunnel' (ssh_host set in data source options) on a query runner whose class does not implement the host/port properties, which raise NotImplementedError on BaseQueryRunner by design.","commonSituations":"Trying to tunnel an HTTP/API-type or other non-protocol runner, or enabling the tunnel checkbox on a runner where tunneling was never implemented.","solutions":["Disable the SSH tunnel option on that data source","Use a query runner type that implements host/port (a SQL driver runner) if tunneling is required","Run an external tunnel (ssh -L) and point the data source at localhost"],"exampleFix":"# before (data source options)\n{\"ssh_tunnel_enabled\": true, \"ssh_host\": \"bastion\"}\n\n# after\n{\"ssh_tunnel_enabled\": false, \"host\": \"127.0.0.1\", \"port\": 5432}  # via ssh -L 5432:db:5432 bastion","handlingStrategy":"validation","validationCode":"if details.get('ssh_host'):\n    try:\n        _ = (query_runner.host, query_runner.port)\n    except NotImplementedError:\n        raise SystemExit('this runner type does not support SSH tunnels')","typeGuard":"def supports_tunnel(runner) -> bool:\n    try:\n        _ = (runner.host, runner.port); return True\n    except NotImplementedError:\n        return False","tryCatchPattern":"try:\n    result = runner.run_query(q, u)\nexcept NotImplementedError as e:\n    if 'SSH tunneling' in str(e):\n        disable_tunnel_and_point_at_local_forward(); retry","preventionTips":["Only enable tunnel options on runner types that implement host/port","Use an external ssh -L tunnel for exotic runners","Document per-runner tunnel support in your data-source catalog"],"tags":["redash","ssh-tunnel","not-implemented","data-source"],"backgroundTag":"unsupported-operation","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}