{"record":{"id":"15e3592ab33cce3f","repo":"python/cpython","slug":"server-hostname-is-only-meaningful-with-ssl","errorCode":null,"errorMessage":"server_hostname is only meaningful with ssl","messagePattern":"server_hostname is only meaningful with ssl","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/asyncio/base_events.py","lineNumber":1087,"sourceCode":"            proto=0, flags=0, sock=None,\n            local_addr=None, server_hostname=None,\n            ssl_handshake_timeout=None,\n            ssl_shutdown_timeout=None,\n            happy_eyeballs_delay=None, interleave=None,\n            all_errors=False):\n        \"\"\"Connect to a TCP server.\n\n        Create a streaming transport connection to a given internet host and\n        port: socket family AF_INET or socket.AF_INET6 depending on host (or\n        family if specified), socket type SOCK_STREAM. protocol_factory must\n        be a callable returning a protocol instance.\n\n        This method is a coroutine which will try to establish the\n        connection in the background.  When successful, the coroutine\n        returns a (transport, protocol) pair.\n        \"\"\"\n        if server_hostname is not None and not ssl:\n            raise ValueError('server_hostname is only meaningful with ssl')\n\n        if server_hostname is None and ssl:\n            # Use host as default for server_hostname.  It is an error\n            # if host is empty or not set, e.g. when an\n            # already-connected socket was passed or when only a port\n            # is given.  To avoid this error, you can pass\n            # server_hostname='' -- this will bypass the hostname\n            # check.  (This also means that if host is a numeric\n            # IP/IPv6 address, we will attempt to verify that exact\n            # address; this will probably fail, but it is possible to\n            # create a certificate for a specific IP address, so we\n            # don't judge it here.)\n            if not host:\n                raise ValueError('You must set server_hostname '\n                                 'when using ssl without a host')\n            server_hostname = host\n\n        if ssl_handshake_timeout is not None and not ssl:","sourceCodeStart":1069,"sourceCodeEnd":1105,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/base_events.py#L1069-L1105","documentation":"Raised by BaseEventLoop.create_connection when the caller passes server_hostname together with ssl=None/False. server_hostname is only used to verify the TLS peer's certificate; without an ssl context/protocol there is no certificate check, so the argument is meaningless and asyncio rejects it to catch configuration mistakes.","triggerScenarios":"Calling loop.create_connection(factory, host, port, server_hostname='example.com') with no ssl= argument (ssl defaults to None). Common when TLS support was removed or made conditional but the hostname argument stayed.","commonSituations":"Feature-flagged TLS: code built the server_hostname string eagerly but passed ssl=None in the plaintext branch; refactors that dropped the ssl argument; testing against a local plaintext server with leftover TLS kwargs.","solutions":["Pass an ssl context: ssl=ssl.create_default_context() alongside server_hostname.","If the connection is intentionally plaintext, drop server_hostname from the call.","Build kwargs conditionally: kwargs['server_hostname'] = name only when ssl is set."],"exampleFix":"// before\nawait loop.create_connection(proto, host, port, server_hostname='example.com')  # no ssl\n\n// after\nkwargs = {}\nif use_tls:\n    kwargs['ssl'] = ssl.create_default_context()\n    kwargs['server_hostname'] = 'example.com'\nawait loop.create_connection(proto, host, port, **kwargs)","handlingStrategy":"validation","validationCode":"if server_hostname is not None and not ssl_ctx:\n    raise ConfigError('server_hostname requires an ssl context')","typeGuard":null,"tryCatchPattern":"try:\n    await loop.create_connection(proto, host, port, server_hostname=name)\nexcept ValueError as e:\n    if 'only meaningful with ssl' not in str(e):\n        raise\n    await loop.create_connection(proto, host, port,\n                                 ssl=ssl.create_default_context(),\n                                 server_hostname=name)","preventionTips":["Build TLS kwargs (ssl, server_hostname, both timeouts) as one atomic dict — set all or none.","Lint for create_connection calls that pass server_hostname without ssl=.","In feature-flagged TLS, branch on the flag before composing kwargs."],"tags":["asyncio","tls","ssl","validation","network"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}