aio-libs/aiohttp · critical · RuntimeError

SSL is not supported.

Error message

SSL is not supported.

What it means

Raised by GunicornWebWorker._create_ssl_context() when the Python `ssl` stdlib module failed to import. The import at the top of worker.py is wrapped in try/except ImportError and falls back to ssl=None; if you then enable SSL in the gunicorn config (certfile/keyfile/ssl_version), the worker cannot build an SSLContext and aborts.

Source

Thrown at aiohttp/worker.py:223

        self.cfg.worker_int(self)

        # wakeup closing process
        self._notify_waiter_done()

    def handle_abort(self, sig: int, frame: FrameType | None) -> None:
        self.alive = False
        self.exit_code = 1
        self.cfg.worker_abort(self)
        sys.exit(1)

    @staticmethod
    def _create_ssl_context(cfg: Any) -> "SSLContext":
        """Creates SSLContext instance for usage in asyncio.create_server.

        See ssl.SSLSocket.__init__ for more details.
        """
        if ssl is None:  # pragma: no cover
            raise RuntimeError("SSL is not supported.")

        ctx = ssl.SSLContext(cfg.ssl_version)
        ctx.load_cert_chain(cfg.certfile, cfg.keyfile)
        ctx.verify_mode = cfg.cert_reqs
        if cfg.ca_certs:
            ctx.load_verify_locations(cfg.ca_certs)
        if cfg.ciphers:
            ctx.set_ciphers(cfg.ciphers)
        return ctx

    def _get_valid_log_format(self, source_format: str) -> str:
        if source_format == self.DEFAULT_GUNICORN_LOG_FORMAT:
            return self.DEFAULT_AIOHTTP_LOG_FORMAT
        elif re.search(r"%\([^\)]+\)", source_format):
            raise ValueError(
                "Gunicorn's style options in form of `%(name)s` are not "
                "supported for the log formatting. Please use aiohttp's "
                "format specification to configure access log formatting: "

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Use a Python build with SSL support: install openssl dev headers and rebuild/reinstall Python, or use an official CPython distribution.
  2. On Alpine install `libssl`/`libcrypto` and `openssl`; on Debian `apt-get install libssl-dev` and rebuild Python.
  3. If SSL is not actually required, disable it in the gunicorn config (remove certfile/keyfile) and terminate TLS at a reverse proxy instead.
  4. Verify with `python -c "import ssl; print(ssl.OPENSSL_VERSION)"` before starting the worker.

Example fix

# verify ssl support first
# python -c 'import ssl; print(ssl.OPENSSL_VERSION)'
# if it fails, rebuild python with openssl, e.g. on debian:
#   apt-get install -y libssl-dev && reinstall/rebuild python

# gunicorn config: only enable ssl when import ssl works
Defensive patterns

Strategy: validation

Validate before calling

import ssl

def assert_ssl_available():
    if ssl is None:
        raise RuntimeError("SSL is not supported by this interpreter")
    return ssl

Type guard

import sys

def has_ssl() -> bool:
    try:
        import ssl
        return True
    except ImportError:
        return False

Prevention

When it happens

Trigger: Running the gunicorn aiohttp worker with SSL enabled (`--certfile`/`--keyfile` or `cfg.is_ssl`) on a Python interpreter compiled without OpenSSL/ssl support, so `import ssl` raised ImportError and ssl is None.

Common situations: A custom or minimal Python build (e.g. some embedded/Alpine images without openssl-dev at compile time); a broken system OpenSSL that prevented the ssl module from building; a container image missing libssl.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/4f3363f1a535bf97.json. Report an issue: GitHub.