pypa/pip · critical · SSLMissingError
ssl-missing
ssl-missing
Error message
Failed to establish a secure connection for {url} What it means
Raised as SSLMissingError in PipSession.request when the underlying request to an HTTPS URL fails with an ImportError whose message mentions 'ssl'. That means the running Python interpreter was built without the _ssl/OpenSSL C extension, so HTTPS is impossible.
Solutions
- Reinstall or rebuild Python with OpenSSL support (install libssl-dev/openssl-devel and reconfigure/recompile).
- Use an official CPython distribution that bundles SSL support.
- Verify with 'python -c "import ssl"' that the interpreter can load _ssl.
- As a last resort only, point pip at an HTTP index (insecure, not recommended).
Defensive patterns
Strategy: validation
Validate before calling
def python_has_ssl() -> bool:
try:
import ssl # noqa: F401
return True
except ImportError:
return False
# assert python_has_ssl() Prevention
- Build/install Python with OpenSSL support (libssl-dev at build time).
- Use official CPython distributions that bundle SSL.
- Validate 'python -c "import ssl"' in image build pipelines.
When it happens
Trigger: Any HTTPS index/download request when Python's _ssl module is unavailable; e.g. a stripped or custom-built CPython lacking OpenSSL linkage, or a broken Python distribution where _ssl.pyd/.so failed to import.
Common situations: Minimal Docker/base images with hand-compiled Python missing libssl-dev; broken Python installs after an OS openssl upgrade relocated the shared lib; embedded Python distributions.
Related errors
- ssl-verification-failed
- Unable to verify server certificate for
- Unexpected HTTP request on what should be a secure…
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/05dc1acea9c2e012.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/network/session.py:548
def request(self, method: str, url: str, *args: Any, **kwargs: Any) -> Response: # type: ignore[override]
# Allow setting a default timeout on a session
kwargs.setdefault("timeout", self.timeout)
# Allow setting a default proxies on a session
kwargs.setdefault("proxies", self.proxies)
# Dispatch the actual request
try:
return super().request(method, url, *args, **kwargs)
except (requests.ConnectionError, requests.Timeout) as e:
request = getattr(e, "request", None)
failed_url = getattr(request, "url", None) or url
raise_connection_error(e, url=failed_url, timeout=kwargs["timeout"])
except ImportError as e:
if "ssl" in str(e).lower():
# Unfortunately, if this TLS error was the result of a redirect from
# a HTTP to a HTTPS url, we don't know what the final url was.
raise SSLMissingError(redact_auth_from_url(url))
raise
View on GitHub (pinned to f399c37189)