{"id":"fc39e8898db05ba7","repo":"aio-libs/aiohttp","slug":"ssl-should-be-sslcontext-fingerprint-or-bool-go","errorCode":null,"errorMessage":"ssl should be SSLContext, Fingerprint, or bool, got {ssl!r} instead.","messagePattern":"ssl should be SSLContext, Fingerprint, or bool, got (.+?) instead\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":340,"sourceCode":"        fallback_charset_resolver: _CharsetResolver = lambda r, b: \"utf-8\",\n        middlewares: Sequence[ClientMiddlewareType] = (),\n        ssl_shutdown_timeout: _SENTINEL | None | float = sentinel,\n    ) -> None:\n        # We initialise _connector to None immediately, as it's referenced in __del__()\n        # and could cause issues if an exception occurs during initialisation.\n        self._connector: BaseConnector | None = None\n        if base_url is None or isinstance(base_url, URL):\n            self._base_url: URL | None = base_url\n            self._base_url_origin = None if base_url is None else base_url.origin()\n        else:\n            self._base_url = URL(base_url)\n            self._base_url_origin = self._base_url.origin()\n            assert self._base_url.absolute, \"Only absolute URLs are supported\"\n        if self._base_url is not None and not self._base_url.path.endswith(\"/\"):\n            raise ValueError(\"base_url must have a trailing '/'\")\n\n        if not isinstance(ssl, SSL_ALLOWED_TYPES):\n            raise TypeError(\n                \"ssl should be SSLContext, Fingerprint, or bool, \"\n                f\"got {ssl!r} instead.\"\n            )\n\n        loop = asyncio.get_running_loop()\n\n        if timeout is sentinel or timeout is None:\n            timeout = ClientTimeout()\n        if not isinstance(timeout, ClientTimeout):\n            raise ValueError(\n                f\"timeout parameter cannot be of {type(timeout)} type, \"\n                \"please use 'timeout=ClientTimeout(...)'\",\n            )\n        self._timeout = timeout\n\n        if ssl_shutdown_timeout is not sentinel:\n            warnings.warn(\n                \"The ssl_shutdown_timeout parameter is deprecated and will be removed in aiohttp 4.0\",","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L322-L358","documentation":"Raised in ClientSession.__init__ (client.py:340) as a TypeError when the ssl argument is not one of the allowed types: ssl.SSLContext, aiohttp.Fingerprint, or bool. SSL_ALLOWED_TYPES is (ssl.SSLContext, bool, Fingerprint) when ssl is importable, else (bool,). Passing anything else (str, dict, tuple, int) is rejected up front to fail fast.","triggerScenarios":"ClientSession(ssl='certfile.pem') or ssl={'verify': True} or ssl=1 — any value whose type is not SSLContext/Fingerprint/bool. Note a path string is NOT accepted; you must build an SSLContext.","commonSituations":"Passing a certificate file path string instead of an SSLContext built from it; passing an int where a bool was expected; passing a config dict from another library; disabling verification incorrectly.","solutions":["To use a cert file, build a context: ssl=ssl.create_default_context(cafile='ca.pem').","To disable verification for a trusted host, pass ssl=False (not ssl=0 or a string).","To pin a server key, pass ssl=aiohttp.Fingerprint(b'...')."],"exampleFix":"# before\nsession = aiohttp.ClientSession(ssl='server.pem')\n\n# after\nimport ssl\nctx = ssl.create_default_context(cafile='server.pem')\nsession = aiohttp.ClientSession(ssl=ctx)","handlingStrategy":"type-guard","validationCode":"import ssl\nfrom aiohttp import Fingerprint\n\ndef make_ssl(v):\n    if isinstance(v, (ssl.SSLContext, Fingerprint, bool)):\n        return v\n    if isinstance(v, str):  # treat as cert path\n        ctx = ssl.create_default_context(cafile=v)\n        return ctx\n    raise TypeError('ssl must be SSLContext, Fingerprint, or bool')","typeGuard":"def is_valid_ssl(v) -> bool:\n    import ssl\n    from aiohttp import Fingerprint\n    return isinstance(v, (ssl.SSLContext, Fingerprint, bool))","tryCatchPattern":"try:\n    session = aiohttp.ClientSession(ssl=ssl_value)\nexcept TypeError:\n    ssl_value = ssl.create_default_context(cafile=str(ssl_value))\n    session = aiohttp.ClientSession(ssl=ssl_value)","preventionTips":["Build an SSLContext from cert files; never pass a path string","Use ssl=False to disable verification, not 0 or a string","Pin keys with aiohttp.Fingerprint"],"tags":["client","ssl","configuration","type-error","constructor"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}