Describe the bug
When connect() fails with no namespace in failed_namespaces, the raised error message is misleading and empty: "One or more namespaces failed to connect: " (a colon followed by nothing).
This happens when the failure occurs before any namespace is attempted — most notably when the auth callable (dynamic auth provider) raises: the engine.io connect handler (_handle_eio_connect) raises during auth evaluation, the exception is swallowed by the engine.io layer (see linked issue), no CONNECT packet is ever sent, and failed_namespaces stays empty. The caller gets a ConnectionError that says nothing was wrong, and the original cause (e.g. RuntimeError: credential fetch failed) is lost.
This is related to (but distinct from) the already-fixed #1507 (missing + join, fixed in 5.14.2): there the list was non-empty but the message lacked separators; here the list is genuinely empty.
To Reproduce
import threading
from wsgiref.simple_server import make_server
import socketio
srv = socketio.Server()
httpd = make_server('127.0.0.1', 0, socketio.WSGIApp(srv))
threading.Thread(target=httpd.serve_forever, daemon=True).start()
port = httpd.server_address[1]
def auth_provider():
raise RuntimeError('credential fetch failed')
sio = socketio.Client()
try:
sio.connect(f'http://127.0.0.1:{port}', auth=auth_provider,
transports=['polling'], wait_timeout=2)
except socketio.exceptions.ConnectionError as exc:
print(repr(exc))
# prints: ConnectionError("One or more namespaces failed to connect: ")
Also reproduces with socketio.AsyncClient.
Expected behavior
The error message should be meaningful — either a non-empty namespace list, or (preferably) the underlying error attached/chained, e.g. "One or more namespaces failed to connect: " should not be printed with nothing after the colon when the real cause is an auth provider failure. At minimum, an empty failed_namespaces should produce a distinct, informative message (e.g. "connection failed before namespaces could be attempted").
Logs
The only clue is the engine.io layer logging the swallowed provider exception:
engineio.client ERROR: connect handler error
Traceback (most recent call last):
...
File ".../socketio/client.py", line 507, in _handle_eio_connect
real_auth = self._get_real_value(self.connection_auth) or {}
File ".../socketio/client.py", line 360, in _get_real_value
return value()
RuntimeError: credential fetch failed
Additional context
Tested on python-socketio 5.14.3 and 5.16.4 (latest) — identical behavior.
Use case: we maintain a Python SDK (A2C-SMCP, an Agent-to-Computer remote tool-calling protocol) whose agent client passes auth to socketio.Client / AsyncClient as a callable — a pluggable credential provider fetching a short-lived token from a vault/API at connect time. When the provider fails, the SDK must surface a clear, actionable connection error; the current empty message makes it impossible to tell from the exception alone what went wrong.
Related: miguelgrinberg/python-engineio#462 (engine.io ignores connect-handler failures, which is the root cause of the empty failed_namespaces in this scenario) and miguelgrinberg/python-socketio#1594 (feature request: auth callable timeout).
Describe the bug
When
connect()fails with no namespace infailed_namespaces, the raised error message is misleading and empty:"One or more namespaces failed to connect: "(a colon followed by nothing).This happens when the failure occurs before any namespace is attempted — most notably when the
authcallable (dynamic auth provider) raises: the engine.io connect handler (_handle_eio_connect) raises during auth evaluation, the exception is swallowed by the engine.io layer (see linked issue), no CONNECT packet is ever sent, andfailed_namespacesstays empty. The caller gets aConnectionErrorthat says nothing was wrong, and the original cause (e.g.RuntimeError: credential fetch failed) is lost.This is related to (but distinct from) the already-fixed #1507 (missing
+join, fixed in 5.14.2): there the list was non-empty but the message lacked separators; here the list is genuinely empty.To Reproduce
Also reproduces with
socketio.AsyncClient.Expected behavior
The error message should be meaningful — either a non-empty namespace list, or (preferably) the underlying error attached/chained, e.g.
"One or more namespaces failed to connect: "should not be printed with nothing after the colon when the real cause is an auth provider failure. At minimum, an emptyfailed_namespacesshould produce a distinct, informative message (e.g. "connection failed before namespaces could be attempted").Logs
The only clue is the engine.io layer logging the swallowed provider exception:
Additional context
Tested on python-socketio 5.14.3 and 5.16.4 (latest) — identical behavior.
Use case: we maintain a Python SDK (A2C-SMCP, an Agent-to-Computer remote tool-calling protocol) whose agent client passes
authtosocketio.Client/AsyncClientas a callable — a pluggable credential provider fetching a short-lived token from a vault/API at connect time. When the provider fails, the SDK must surface a clear, actionable connection error; the current empty message makes it impossible to tell from the exception alone what went wrong.Related: miguelgrinberg/python-engineio#462 (engine.io ignores connect-handler failures, which is the root cause of the empty
failed_namespacesin this scenario) and miguelgrinberg/python-socketio#1594 (feature request: auth callable timeout).