Linux-6.6.87.1-microsoft-standard-WSL2-x86_64-with-glibc2.41 (but the issue is platform agnostic)
Sometimes, when attempting to connect to snowflake with SSO via external browser authentication, running the code in a linux devcontainer on wsl2, I experience an error at
where it fails to split the string into 3 pieces.
does not correctly parse the incoming tcp byte stream to completion. Once it receives any amount of bytes through the socket it moves on to decode and then process the received data. There is no guarantee that the entire message is received in a single call to
, so it may or may not have everything it needs to properly process the token.
There is special handling for receiving 0 bytes in containerised environments to begin with and using socket.MSG_DONTWAIT etc., but that is tangential to the fact that there is no guarantee that a single call to socket.recv() will receive all the data that is being transmitted, even when you specify an arbitarily large BUF_SIZE. This error could occur on any platform, whether in a containerised application or not, because the basic assumption that a single call to socket.recv() will get all the data that is being transmitted is incorrect. You have to repeatedly call recv until you've received everything or do some fancy parsing after receiving some amount of bytes to check if you have what you need before closing the socket.
I have done a little tinkering with a minimal fix, but it's pretty tricky at the socket level, it might be easier/safer/less bug prone to instantiate a proper httpserver but it's a much larger amount of code to change
Note I actually caught this while running via the vscode debugger so there's a bunch of extra frames in the traceback. It does occur outside the debugger as well
2026-03-27 01:22:55,000 - my-package-runner config_manager.py:359 - read_config() - DEBUG - Fail to read configuration file from /root/.config/snowflake/config.toml due to no permission on its parent directory
2026-03-27 01:22:55,001 - my-package-runner config_manager.py:359 - read_config() - DEBUG - Fail to read configuration file from /root/.config/snowflake/connections.toml due to no permission on its parent directory
2026-03-27 01:22:55,001 - my-package-runner connection.py:620 - __init__() - INFO - Snowflake Connector for Python Version: 4.4.0, Python Version: 3.12.12, Platform: Linux-6.6.87.1-microsoft-standard-WSL2-x86_64-with-glibc2.41
2026-03-27 01:22:55,002 - my-package-runner connection.py:1120 - connect() - DEBUG - connect
2026-03-27 01:22:55,002 - my-package-runner connection.py:1638 - __config() - DEBUG - __config
2026-03-27 01:22:55,002 - my-package-runner connection.py:1716 - __config() - INFO - Connecting to GLOBAL Snowflake domain
2026-03-27 01:22:55,002 - my-package-runner connection.py:1852 - __config() - DEBUG - This connection is in OCSP Fail Open Mode. TLS Certificates would be checked for validity and revocation status. Any other Certificate Revocation related exceptions or OCSP Responder failures would be disregarded in favor of connectivity.
2026-03-27 01:22:55,003 - my-package-runner converter.py:156 - __init__() - DEBUG - use_numpy: False
2026-03-27 01:22:55,003 - my-package-runner connection.py:1366 - __open_connection() - DEBUG - REST API object was created: REDACTED_URL
2026-03-27 01:22:55,004 - my-package-runner webbrowser.py:113 - prepare() - DEBUG - authenticating by Web Browser
2026-03-27 01:22:55,004 - my-package-runner webbrowser.py:148 - prepare() - DEBUG - step 1: query GS to obtain SSO url
2026-03-27 01:23:10,510 - my-package-runner platform_detection.py:549 - detect_platforms() - DEBUG - Platform detection completed. Detected platforms: ['has_aws_identity_timeout', 'is_gce_vm_timeout', 'has_gcp_identity_timeout']
2026-03-27 01:23:10,511 - my-package-runner webbrowser.py:481 - _get_sso_url() - DEBUG - account=REDACTED, authenticator=EXTERNALBROWSER, user=REDACTED
2026-03-27 01:23:10,515 - my-package-runner retry.py:298 - from_int() - DEBUG - Converted retries value: 1 -> Retry(total=1, connect=None, read=None, redirect=None, status=None)
2026-03-27 01:23:10,516 - my-package-runner network.py:906 - _request_exec_wrapper() - DEBUG - remaining request timeout: N/A ms, retry cnt: 1
2026-03-27 01:23:10,517 - my-package-runner network.py:887 - add_request_guid() - DEBUG - Request guid: REDACTED
2026-03-27 01:23:10,517 - my-package-runner network.py:1091 - _request_exec() - DEBUG - socket timeout: 60
2026-03-27 01:23:10,520 - my-package-runner connectionpool.py:1049 - _new_conn() - DEBUG - Starting new HTTPS connection (1): REDACTED_URL
2026-03-27 01:23:10,625 - my-package-runner ssl_wrap_socket.py:196 - ssl_wrap_socket_with_cert_revocation_checks() - DEBUG - CRL Check Mode: DISABLED
2026-03-27 01:23:10,625 - my-package-runner ssl_wrap_socket.py:224 - ssl_wrap_socket_with_cert_revocation_checks() - DEBUG - OCSP Mode: FAIL_OPEN, OCSP response cache file name: None
2026-03-27 01:23:10,643 - my-package-runner ocsp_snowflake.py:679 - reset_cache_dir() - DEBUG - cache directory: /root/.cache/snowflake
2026-03-27 01:23:10,646 - my-package-runner ocsp_snowflake.py:717 - reset_ocsp_response_cache_uri() - DEBUG - ocsp_response_cache_uri: file:///root/.cache/snowflake/ocsp_response_cache.json
2026-03-27 01:23:10,646 - my-package-runner ocsp_snowflake.py:720 - reset_ocsp_response_cache_uri() - DEBUG - OCSP_VALIDATION_CACHE size: 303
2026-03-27 01:23:10,646 - my-package-runner ocsp_snowflake.py:512 - reset_ocsp_dynamic_cache_server_url() - DEBUG - OCSP response cache server is enabled: http://ocsp.snowflakecomputing.com/ocsp_response_cache.json
2026-03-27 01:23:10,646 - my-package-runner ocsp_snowflake.py:525 - reset_ocsp_dynamic_cache_server_url() - DEBUG - OCSP dynamic cache server RETRY URL: None
2026-03-27 01:23:10,647 - my-package-runner ocsp_snowflake.py:1160 - validate() - DEBUG - validating certificate: REDACTED_URL
2026-03-27 01:23:10,647 - my-package-runner ocsp_asn1crypto.py:398 - extract_certificate_chain() - DEBUG - # of certificates: 3
2026-03-27 01:23:10,672 - my-package-runner ocsp_asn1crypto.py:87 - read_cert_bundle() - DEBUG - reading certificate bundle: /root/.cache/uv-venv/my-package/lib/python3.12/site-packages/certifi/cacert.pem
2026-03-27 01:23:10,681 - my-package-runner ocsp_asn1crypto.py:403 - extract_certificate_chain() - DEBUG - subject: OrderedDict({'country_name': 'US', 'state_or_province_name': 'Montana', 'locality_name': 'Bozeman', 'organization_name': 'Snowflake Inc.', 'common_name': '*.aws_region.aws.snowflakecomputing.com'}), issuer: OrderedDict({'country_name': 'US', 'organization_name': 'DigiCert Inc', 'common_name': 'DigiCert Global G2 TLS RSA SHA256 2020 CA1'})
2026-03-27 01:23:10,681 - my-package-runner ocsp_asn1crypto.py:403 - extract_certificate_chain() - DEBUG - subject: OrderedDict({'country_name': 'US', 'organization_name': 'DigiCert Inc', 'common_name': 'DigiCert Global G2 TLS RSA SHA256 2020 CA1'}), issuer: OrderedDict({'country_name': 'US', 'organization_name': 'DigiCert Inc', 'organizational_unit_name': 'www.digicert.com', 'common_name': 'DigiCert Global Root G2'})
2026-03-27 01:23:10,681 - my-package-runner ocsp_asn1crypto.py:408 - extract_certificate_chain() - DEBUG - A trusted root certificate found: OrderedDict({'country_name': 'US', 'organization_name': 'DigiCert Inc', 'common_name': 'DigiCert Global G2 TLS RSA SHA256 2020 CA1'}), stopping chain traversal here
2026-03-27 01:23:10,683 - my-package-runner ocsp_asn1crypto.py:432 - create_pair_issuer_subject() - DEBUG - not found issuer_der: OrderedDict({'country_name': 'US', 'organization_name': 'DigiCert Inc', 'organizational_unit_name': 'www.digicert.com', 'common_name': 'DigiCert Global Root G2'})
2026-03-27 01:23:10,684 - my-package-runner ocsp_snowflake.py:917 - find_cache() - DEBUG - hit cache for subject: OrderedDict({'country_name': 'US', 'state_or_province_name': 'Montana', 'locality_name': 'Bozeman', 'organization_name': 'Snowflake Inc.', 'common_name': '*.aws_region.aws.snowflakecomputing.com'})
2026-03-27 01:23:10,685 - my-package-runner ocsp_snowflake.py:917 - find_cache() - DEBUG - hit cache for subject: OrderedDict({'country_name': 'US', 'organization_name': 'DigiCert Inc', 'common_name': 'DigiCert Global G2 TLS RSA SHA256 2020 CA1'})
2026-03-27 01:23:10,686 - my-package-runner ocsp_snowflake.py:1217 - _validate() - DEBUG - ok
2026-03-27 01:23:10,725 - my-package-runner connectionpool.py:544 - _make_request() - DEBUG - REDACTED_URL "POST /session/authenticator-request?request_guid=REDACTED HTTP/1.1" 200 None
2026-03-27 01:23:10,727 - my-package-runner network.py:1123 - _request_exec() - DEBUG - SUCCESS
2026-03-27 01:23:10,727 - my-package-runner network.py:766 - _post_request() - DEBUG - ret[code] = None, after post request
2026-03-27 01:23:10,727 - my-package-runner webbrowser.py:156 - prepare() - DEBUG - Validate SSO URL
Initiating login request with your identity provider. Press CTRL+C to abort and try again...
2026-03-27 01:23:10,727 - my-package-runner webbrowser.py:171 - prepare() - DEBUG - step 2: open a browser
Going to open: REDACTED_URL to authenticate...
A browser window should have opened for you to complete the login. If you can't see it, check existing browser windows, or your OS settings.
2026-03-27 01:23:10,814 - my-package-runner webbrowser.py:185 - prepare() - DEBUG - step 3: accept SAML token
2026-03-27 01:23:13,347 - my-package-runner webbrowser.py:258 - _receive_saml_token() - DEBUG - Calling socket_client.recv with MSG_DONTWAIT flag due to SNOWFLAKE_AUTH_SOCKET_MSG_DONTWAIT env var
2026-03-27 01:30:13,282 - analyse-transcripts-runner webbrowser.py:443 - _get_user_agent() - DEBUG - No User-Agent
Traceback (most recent call last):
File "/usr/local/lib/python3.12/runpy.py", line 198, in _run_module_as_main
return _run_code(code, main_globals, None,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/runpy.py", line 88, in _run_code
exec(code, run_globals)
File "/root/.vscode-server/extensions/ms-python.debugpy-2025.18.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 71, in <module>
cli.main()
File "/root/.vscode-server/extensions/ms-python.debugpy-2025.18.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 508, in main
run()
File "/root/.vscode-server/extensions/ms-python.debugpy-2025.18.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 358, in run_file
runpy.run_path(target, run_name="__main__")
File "/root/.vscode-server/extensions/ms-python.debugpy-2025.18.0-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 310, in run_path
return _run_module_code(code, init_globals, run_name, pkg_name=pkg_name, script_name=fname)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/.vscode-server/extensions/ms-python.debugpy-2025.18.0-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 127, in _run_module_code
_run_code(code, mod_globals, init_globals, mod_name, mod_spec, pkg_name, script_name)
File "/root/.vscode-server/extensions/ms-python.debugpy-2025.18.0-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 118, in _run_code
exec(code, run_globals)
File "/workspaces/my-package/debug/debug.py", line 18, in <module>
run()
File "/workspaces/my-package/src/my_package/__init__.py", line 30, in run
return future.result()
^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 449, in result
return self.__get_result()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
raise self._exception
File "/workspaces/my-package/src/my_package/__init__.py", line 20, in _run_in_worker
asyncio.run(analyse_transcripts())
File "/usr/local/lib/python3.12/asyncio/runners.py", line 195, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/asyncio/base_events.py", line 691, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/workspaces/my-package/src/my_package/main.py", line 22, in analyse_transcripts
conn = SnowflakeHelper()
^^^^^^^^^^^^^^^^^
File "/workspaces/my-package/src/my_package/utils/snowflake.py", line 19, in __init__
self._conn = self._connect()
^^^^^^^^^^^^^^^
File "/workspaces/my-package/src/my_package/utils/snowflake.py", line 49, in _connect
return snowflake.connector.connect(**self.connection_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/__init__.py", line 64, in Connect
return SnowflakeConnection(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/connection.py", line 688, in __init__
self.connect(**kwargs)
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/connection.py", line 1184, in connect
self.__open_connection()
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/connection.py", line 1623, in __open_connection
self.authenticate_with_retry(self.auth_class)
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/connection.py", line 1959, in authenticate_with_retry
self._authenticate(auth_instance)
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/connection.py", line 1975, in _authenticate
auth_instance.prepare(
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/auth/webbrowser.py", line 186, in prepare
self._receive_saml_token(conn, socket_connection)
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/auth/webbrowser.py", line 283, in _receive_saml_token
self._process_receive_saml_token(conn, data, socket_client)
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/auth/webbrowser.py", line 340, in _process_receive_saml_token
if not self._process_get(data) and not self._process_post(conn, data):
^^^^^^^^^^^^^^^^^^^^^^^
File "/root/.cache/uv-venv/my-package/lib/python3.12/site-packages/snowflake/connector/auth/webbrowser.py", line 407, in _process_get
_, url, _ = target_line.split()
^^^^^^^^^
ValueError: not enough values to unpack (expected 3, got 2)
Python version
3.12.12 (but the issues is version agnostic)
Operating system and processor architecture
Linux-6.6.87.1-microsoft-standard-WSL2-x86_64-with-glibc2.41 (but the issue is platform agnostic)
Installed packages
What did you do?
What did you expect to see?
Sometimes, when attempting to connect to snowflake with SSO via external browser authentication, running the code in a linux devcontainer on wsl2, I experience an error at
snowflake-connector-python/src/snowflake/connector/auth/webbrowser.py
Line 407 in 225b237
where it fails to split the string into 3 pieces.
The reason this occurs is because
_receive_saml_tokenatsnowflake-connector-python/src/snowflake/connector/auth/webbrowser.py
Line 265 in 225b237
does not correctly parse the incoming tcp byte stream to completion. Once it receives any amount of bytes through the socket it moves on to decode and then process the received data. There is no guarantee that the entire message is received in a single call to
socket.recv(), so it may or may not have everything it needs to properly process the token.There is special handling for receiving 0 bytes in containerised environments to begin with and using
socket.MSG_DONTWAITetc., but that is tangential to the fact that there is no guarantee that a single call tosocket.recv()will receive all the data that is being transmitted, even when you specify an arbitarily largeBUF_SIZE. This error could occur on any platform, whether in a containerised application or not, because the basic assumption that a single call tosocket.recv()will get all the data that is being transmitted is incorrect. You have to repeatedly callrecvuntil you've received everything or do some fancy parsing after receiving some amount of bytes to check if you have what you need before closing the socket.I see a todo at the top of the file that you want to convert it over to the new
AuthHttpServerclass, but that also has the same problem.I have done a little tinkering with a minimal fix, but it's pretty tricky at the socket level, it might be easier/safer/less bug prone to instantiate a proper httpserver but it's a much larger amount of code to change
Can you set logging to DEBUG and collect the logs?