aio-libs/aiohttp · error · TypeError

ssl should be SSLContext, Fingerprint, or bool, got

Error message

ssl should be SSLContext, Fingerprint, or bool, got {ssl!r} instead.

What it means

Raised by ClientSession.__init__ when the ssl argument is not an SSLContext, Fingerprint, or bool (the union SSL_ALLOWED_TYPES). aiohttp needs a concrete TLS configuration object; arbitrary values cannot be coerced. Unlike requests, a file path string is not accepted.

Solutions

  1. Pass a bool for default verification: ClientSession(ssl=True) (or False to disable verification).
  2. Load an SSLContext: ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile='ca.pem'); ClientSession(ssl=ctx).
  3. Pass a Fingerprint for certificate pinning: Fingerprint(hashlib.sha256(der).digest()).

Example fix

// before
session = ClientSession(ssl='cert.pem')
// after
import ssl as _ssl
ctx = _ssl.create_default_context(ssl.Purpose.SERVER_AUTH, cafile='cert.pem')
session = ClientSession(ssl=ctx)
Defensive patterns

Strategy: type-guard

Validate before calling

import ssl as _ssl
from aiohttp import TCPConnector
from aiohttp.typedefs import PathLike  # if available

SSL_ALLOWED = (bool, _ssl.SSLContext)
# Note: Fingerprint is also allowed; import from aiohttp

def to_ssl_arg(value):
    if isinstance(value, bool) or isinstance(value, _ssl.SSLContext):
        return value
    raise TypeError('ssl must be bool or SSLContext')

Type guard

import ssl as _ssl
from aiohttp import Fingerprint

def is_valid_ssl(v) -> bool:
    return isinstance(v, (bool, _ssl.SSLContext, Fingerprint))

Try / catch

try:
    session = ClientSession(ssl=value)
except TypeError as e:
    if 'ssl should be' in str(e):
        raise SystemExit('Provide an SSLContext, Fingerprint, or bool for ssl')
    raise

Prevention

When it happens

Trigger: Calling ClientSession(ssl='cert.pem'), ClientSession(ssl='TLSv1'), or passing a dict, int, or None where None is not the default sentinel. The isinstance(ssl, SSL_ALLOWED_TYPES) check fails.

Common situations: Migrating from requests where verify='cert.pem' / cert='path' strings are valid. Storing ssl config in a YAML/dict and passing the dict directly. Confusing the ssl flag with a cipher or protocol name string.

Understand the failure class

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/fc39e8898db05ba7. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/client.py:340

        fallback_charset_resolver: _CharsetResolver = lambda r, b: "utf-8",
        middlewares: Sequence[ClientMiddlewareType] = (),
        ssl_shutdown_timeout: _SENTINEL | None | float = sentinel,
    ) -> None:
        # We initialise _connector to None immediately, as it's referenced in __del__()
        # and could cause issues if an exception occurs during initialisation.
        self._connector: BaseConnector | None = None
        if base_url is None or isinstance(base_url, URL):
            self._base_url: URL | None = base_url
            self._base_url_origin = None if base_url is None else base_url.origin()
        else:
            self._base_url = URL(base_url)
            self._base_url_origin = self._base_url.origin()
            assert self._base_url.absolute, "Only absolute URLs are supported"
        if self._base_url is not None and not self._base_url.path.endswith("/"):
            raise ValueError("base_url must have a trailing '/'")

        if not isinstance(ssl, SSL_ALLOWED_TYPES):
            raise TypeError(
                "ssl should be SSLContext, Fingerprint, or bool, "
                f"got {ssl!r} instead."
            )

        loop = asyncio.get_running_loop()

        if timeout is sentinel or timeout is None:
            timeout = ClientTimeout()
        if not isinstance(timeout, ClientTimeout):
            raise ValueError(
                f"timeout parameter cannot be of {type(timeout)} type, "
                "please use 'timeout=ClientTimeout(...)'",
            )
        self._timeout = timeout

        if ssl_shutdown_timeout is not sentinel:
            warnings.warn(
                "The ssl_shutdown_timeout parameter is deprecated and will be removed in aiohttp 4.0",

View on GitHub (pinned to d041d4d0fd)