{"record":{"id":"741f69adc170f3be","repo":"python/cpython","slug":"sslcontext-is-expected-to-be-an-instance-of-ssl-ss","errorCode":null,"errorMessage":"sslcontext is expected to be an instance of ssl.SSLContext, got {sslcontext!r}","messagePattern":"sslcontext is expected to be an instance of ssl\\.SSLContext, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/asyncio/base_events.py","lineNumber":1343,"sourceCode":"            if total_sent > 0 and hasattr(file, 'seek'):\n                file.seek(offset + total_sent)\n            await proto.restore()\n\n    async def start_tls(self, transport, protocol, sslcontext, *,\n                        server_side=False,\n                        server_hostname=None,\n                        ssl_handshake_timeout=None,\n                        ssl_shutdown_timeout=None):\n        \"\"\"Upgrade transport to TLS.\n\n        Return a new transport that *protocol* should start using\n        immediately.\n        \"\"\"\n        if ssl is None:\n            raise RuntimeError('Python ssl module is not available')\n\n        if not isinstance(sslcontext, ssl.SSLContext):\n            raise TypeError(\n                f'sslcontext is expected to be an instance of ssl.SSLContext, '\n                f'got {sslcontext!r}')\n\n        if not getattr(transport, '_start_tls_compatible', False):\n            raise TypeError(\n                f'transport {transport!r} is not supported by start_tls()')\n\n        waiter = self.create_future()\n        ssl_protocol = sslproto.SSLProtocol(\n            self, protocol, sslcontext, waiter,\n            server_side, server_hostname,\n            ssl_handshake_timeout=ssl_handshake_timeout,\n            ssl_shutdown_timeout=ssl_shutdown_timeout,\n            call_connection_made=False)\n\n        # Pause early so that \"ssl_protocol.data_received()\" doesn't\n        # have a chance to get called before \"ssl_protocol.connection_made()\".\n        transport.pause_reading()","sourceCodeStart":1325,"sourceCodeEnd":1361,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/base_events.py#L1325-L1361","documentation":"A TypeError raised by loop.start_tls() when the sslcontext argument is not an ssl.SSLContext instance. start_tls uses the context to configure certificates, protocols and verification; passing anything else (a boolean like ssl.CERT_REQUIRED, a string path, or None) is rejected with the offending value shown.","triggerScenarios":"Calling loop.start_tls(transport, protocol, ssl.CERT_REQUIRED) — passing a verify-mode constant instead of a context; passing a PEM filename; passing None expecting a default context (there is none).","commonSituations":"Confusing ssl module constants with contexts (CERT_REQUIRED etc. are ints); porting code that used ssl.wrap_socket's looser arguments; forgetting ssl.create_default_context() when building the call.","solutions":["Create a real context: ctx = ssl.create_default_context() (client) or ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) with load_cert_chain (server).","Set verify options on the context (ctx.verify_mode = ssl.CERT_REQUIRED), not as the argument itself.","Type-check the variable early if it comes from dynamic configuration."],"exampleFix":"# before\ntransport = await loop.start_tls(tp, proto, ssl.CERT_REQUIRED)  # TypeError\n\n# after\nctx = ssl.create_default_context()\nctx.check_hostname = True\ntransport = await loop.start_tls(tp, proto, ctx)","handlingStrategy":"type-guard","validationCode":"import ssl\nassert isinstance(ctx, ssl.SSLContext), 'start_tls requires an ssl.SSLContext'","typeGuard":"import ssl\n\ndef is_ssl_context(obj: object) -> bool:\n    return isinstance(obj, ssl.SSLContext)","tryCatchPattern":"try:\n    tp = await loop.start_tls(raw_tp, proto, ctx)\nexcept TypeError as e:\n    if 'ssl.SSLContext' not in str(e):\n        raise\n    ctx = ssl.create_default_context()\n    tp = await loop.start_tls(raw_tp, proto, ctx)","preventionTips":["Always construct contexts via ssl.create_default_context() or SSLContext(PROTOCOL_TLS_*).","Set verify_mode/check_hostname on the context object, never pass ssl constants as the context.","Type-annotate sslcontext parameters as ssl.SSLContext so static checkers catch misuse."],"tags":["asyncio","tls","ssl","type-error","validation"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}