Skip to content

Empty, misleading error message on connect failure: "One or more namespaces failed to connect: " #1595

Description

@JIAQIA

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions