Skip to content

Commit 7ddbf31

Browse files
authored
SNOW-799381: improve error message when hitting ssl related error (#2074)
1 parent 8e2b757 commit 7ddbf31

File tree

6 files changed

+53
-4
lines changed

6 files changed

+53
-4
lines changed

DESCRIPTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
99
# Release Notes
1010

1111
- v3.12.3(TBD)
12+
- Improved the error message for SSL-related issues to provide clearer guidance when an SSL error occurs.
1213
- Improved error message for SQL execution cancellations caused by timeout.
1314

1415
- v3.12.2(September 11,2024)

src/snowflake/connector/connection.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
from .config_manager import CONFIG_MANAGER, _get_default_connection_params
5353
from .connection_diagnostic import ConnectionDiagnostic
5454
from .constants import (
55+
_CONNECTIVITY_ERR_MSG,
5556
_DOMAIN_NAME_MAP,
5657
ENV_VAR_PARTNER,
5758
PARAMETER_AUTOCOMMIT,
@@ -1455,6 +1456,8 @@ def _authenticate(self, auth_instance: AuthByPlugin):
14551456
)
14561457
except OperationalError as auth_op:
14571458
if auth_op.errno == ER_FAILED_TO_CONNECT_TO_DB:
1459+
if _CONNECTIVITY_ERR_MSG in e.msg:
1460+
auth_op.msg += f"\n{_CONNECTIVITY_ERR_MSG}"
14581461
raise auth_op from e
14591462
logger.debug("Continuing authenticator specific timeout handling")
14601463
continue

src/snowflake/connector/constants.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,3 +428,9 @@ class IterUnit(Enum):
428428

429429

430430
_DOMAIN_NAME_MAP = {_DEFAULT_HOSTNAME_TLD: "GLOBAL", _CHINA_HOSTNAME_TLD: "CHINA"}
431+
432+
_CONNECTIVITY_ERR_MSG = (
433+
"Verify that the hostnames and port numbers in SYSTEM$ALLOWLIST are added to your firewall's allowed list."
434+
"\nTo further troubleshoot your connection you may reference the following article: "
435+
"https://docs.snowflake.com/en/user-guide/client-connectivity-troubleshooting/overview."
436+
)

src/snowflake/connector/network.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
urlparse,
4747
)
4848
from .constants import (
49+
_CONNECTIVITY_ERR_MSG,
4950
_SNOWFLAKE_HOST_SUFFIX_REGEX,
5051
HTTP_HEADER_ACCEPT,
5152
HTTP_HEADER_CONTENT_TYPE,
@@ -1134,8 +1135,19 @@ def _request_exec(
11341135
finally:
11351136
raw_ret.close() # ensure response is closed
11361137
except SSLError as se:
1137-
logger.debug("Hit non-retryable SSL error, %s", str(se))
1138-
1138+
msg = f"Hit non-retryable SSL error, {str(se)}.\n{_CONNECTIVITY_ERR_MSG}"
1139+
logger.debug(msg)
1140+
# the following code is for backward compatibility with old versions of python connector which calls
1141+
# self._handle_unknown_error to process SSLError
1142+
Error.errorhandler_wrapper(
1143+
self._connection,
1144+
None,
1145+
OperationalError,
1146+
{
1147+
"msg": msg,
1148+
"errno": ER_FAILED_TO_REQUEST,
1149+
},
1150+
)
11391151
except (
11401152
BadStatusLine,
11411153
ConnectionError,

test/unit/test_connection.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from __future__ import annotations
77

88
import json
9+
import logging
910
import os
1011
import stat
1112
import sys
@@ -41,7 +42,11 @@
4142
try: # pragma: no cover
4243
from snowflake.connector.auth import AuthByUsrPwdMfa
4344
from snowflake.connector.config_manager import CONFIG_MANAGER
44-
from snowflake.connector.constants import ENV_VAR_PARTNER, QueryStatus
45+
from snowflake.connector.constants import (
46+
_CONNECTIVITY_ERR_MSG,
47+
ENV_VAR_PARTNER,
48+
QueryStatus,
49+
)
4550
except ImportError:
4651
ENV_VAR_PARTNER = "SF_PARTNER"
4752
QueryStatus = CONFIG_MANAGER = None
@@ -546,3 +551,19 @@ def test_request_guid():
546551
and SnowflakeRestful.add_request_guid("https://test.abc.cn?a=b")
547552
== "https://test.abc.cn?a=b"
548553
)
554+
555+
556+
@pytest.mark.skipolddriver
557+
def test_ssl_error_hint(caplog):
558+
from snowflake.connector.vendored.requests.exceptions import SSLError
559+
560+
with mock.patch(
561+
"snowflake.connector.vendored.requests.sessions.Session.request",
562+
side_effect=SSLError("SSL error"),
563+
), caplog.at_level(logging.DEBUG):
564+
with pytest.raises(OperationalError) as exc:
565+
fake_connector()
566+
assert _CONNECTIVITY_ERR_MSG in exc.value.msg and isinstance(
567+
exc.value, OperationalError
568+
)
569+
assert "SSL error" in caplog.text and _CONNECTIVITY_ERR_MSG in caplog.text

test/unit/test_util.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
#
22
# Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
33
#
4+
import pytest
45

5-
from snowflake.connector._utils import _TrackedQueryCancellationTimer
6+
try:
7+
from snowflake.connector._utils import _TrackedQueryCancellationTimer
8+
except ImportError:
9+
pass
10+
11+
pytestmark = pytest.mark.skipolddriver
612

713

814
def test_timer():

0 commit comments

Comments
 (0)