urllib3/urllib3 · critical · ImportError

'cryptography' module missing required functionality. Try u

Error message

'cryptography' module missing required functionality.  Try upgrading to v1.3.4 or newer.

What it means

Raised by pyopenssl._validate_dependencies_met() when the installed 'cryptography' package predates v1.3.4 and lacks Extensions.get_extension_for_class. urllib3's pyOpenSSL contrib shim relies on that method, so it refuses to monkey-patch itself in and instructs the user to upgrade cryptography. It fires at injection time (when the contrib module is wired into urllib3).

Source

Thrown at src/urllib3/contrib/pyopenssl.py:170

def extract_from_urllib3() -> None:
    "Undo monkey-patching by :func:`inject_into_urllib3`."

    util.SSLContext = orig_util_SSLContext
    util.ssl_.SSLContext = orig_util_SSLContext
    util.IS_PYOPENSSL = False
    util.ssl_.IS_PYOPENSSL = False


def _validate_dependencies_met() -> None:
    """
    Verifies that PyOpenSSL's package-level dependencies have been met.
    Throws `ImportError` if they are not met.
    """
    # Method added in `cryptography==1.1`; not available in older versions
    from cryptography.x509.extensions import Extensions

    if getattr(Extensions, "get_extension_for_class", None) is None:
        raise ImportError(
            "'cryptography' module missing required functionality.  "
            "Try upgrading to v1.3.4 or newer."
        )

    # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509
    # attribute is only present on those versions.
    from OpenSSL.crypto import X509

    x509 = X509()
    if getattr(x509, "_x509", None) is None:
        raise ImportError(
            "'pyOpenSSL' module missing required functionality. "
            "Try upgrading to v0.14 or newer."
        )


def _dnsname_to_stdlib(name: str) -> str | None:
    """

View on GitHub (pinned to c8d039c1b7)

Solutions

  1. Upgrade the cryptography package: `pip install -U cryptography` (target >= 1.3.4, but in practice use a current release).
  2. Refresh all TLS-related pins together (cryptography + pyOpenSSL).
  3. If you don't actually need the pyOpenSSL shim, stop importing urllib3.contrib.pyopenssl and use urllib3's native ssl backend.

Example fix

// before
$ pip install cryptography==1.2  # too old

// after
$ pip install -U cryptography pyOpenSSL
Defensive patterns

Strategy: validation

Validate before calling

def cryptography_ok() -> bool:
    try:
        from cryptography.x509.extensions import Extensions
        return getattr(Extensions, 'get_extension_for_class', None) is not None
    except Exception:
        return False

Try / catch

try:
    import urllib3.contrib.pyopenssl  # triggers validation
except ImportError as e:
    if 'cryptography' in str(e):
        raise SystemExit('Upgrade cryptography: pip install -U cryptography')
    raise

Prevention

When it happens

Trigger: Importing urllib3.contrib.pyopenssl (or code that injects it) in an environment with cryptography < 1.3.4; a legacy pinned stack where cryptography is intentionally old; a fresh env that pulled an ancient transitive cryptography version.

Common situations: Long-running legacy projects with frozen dependency pins; systems where the OS package provides an old python-cryptography; upgrading pyOpenSSL without also upgrading cryptography.

Related errors


AI-assisted analysis of urllib3/urllib3@c8d039c1b7 (2026-08-04). Data as JSON: /data/errors/6a8eac6e56680a65.json. Report an issue: GitHub.