pypa/pip · error · CertificateError
Unable to verify server certificate for %s
Error message
Unable to verify server certificate for %s
What it means
Raised by HTTPSHandler.https_open() when an HTTPS request fails with a URLError whose reason contains 'certificate verify failed'. distlib re-wraps this as a ssl.CertificateError (subclass of ValueError) named 'Unable to verify server certificate for <host>', indicating the server's TLS certificate could not be validated against the configured CA bundle or hostname.
Source
Thrown at src/pip/_vendor/distlib/util.py:1542
pass a connection class to do_open, but it doesn't actually check for
a class, and just expects a callable. As long as we behave just as a
constructor would have, we should be OK. If it ever changes so that
we *must* pass a class, we'll create an UnsafeHTTPSConnection class
which just sets check_domain to False in the class definition, and
choose which one to pass to do_open.
"""
result = HTTPSConnection(*args, **kwargs)
if self.ca_certs:
result.ca_certs = self.ca_certs
result.check_domain = self.check_domain
return result
def https_open(self, req):
try:
return self.do_open(self._conn_maker, req)
except URLError as e:
if 'certificate verify failed' in str(e.reason):
raise CertificateError('Unable to verify server certificate '
'for %s' % req.host)
else:
raise
#
# To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The-
# Middle proxy using HTTP listens on port 443, or an index mistakenly serves
# HTML containing a http://xyz link when it should be https://xyz),
# you can use the following handler class, which does not allow HTTP traffic.
#
# It works by inheriting from HTTPHandler - so build_opener won't add a
# handler for HTTP itself.
#
class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler):
def http_open(self, req):
raise URLError('Unexpected HTTP request on what should be a secure '
'connection: %s' % req)View on GitHub (pinned to d7d0d0a394)
Solutions
- Update the system CA store (e.g. 'apt-get install --reinstall ca-certificates' / 'update-ca-certificates').
- Point ca_certs at the correct PEM bundle (e.g. certifi's cacert.pem or your org's bundle).
- Fix system clock skew (NTP) so cert validity periods are evaluated correctly.
- As a last resort on trusted networks, disable verification explicitly rather than letting it fail silently, and document the risk.
Example fix
// before index = PackageIndex(..., ca_certs='/missing/bundle.pem') // after import certifi index = PackageIndex(..., ca_certs=certifi.where())
Defensive patterns
Strategy: validation
Validate before calling
import os, ssl
def ca_bundle_is_usable(ca_certs):
if not ca_certs or not os.path.exists(ca_certs):
return False
try:
ctx = ssl.create_default_context(cafile=ca_certs)
ctx.get_ca_certs() # forces load
return True
except ssl.SSLError:
return False
def safe_index(url, ca_certs):
if not ca_bundle_is_usable(ca_certs):
raise ValueError('CA bundle missing or invalid: %r' % ca_certs)
# proceed to build PackageIndex/HTTPSHandler with ca_certs Try / catch
from ssl import CertificateError
try:
opener.open(req)
except CertificateError as e:
if 'Unable to verify server certificate' in str(e):
refresh_ca_bundle() # update ca-certificates / certifi
# then retry once; do NOT silently disable verification in production
opener.open(req)
else:
raise Prevention
- Keep the OS CA store and certifi up to date.
- Point ca_certs at a verified PEM bundle and validate it loads before use.
- Sync the system clock via NTP so certificate validity windows are correct.
- For corporate CAs, add the root to the trust store rather than disabling verification.
When it happens
Trigger: Configuring a PackageIndex/HTTPSHandler with ca_certs pointing at a missing/expired CA bundle, connecting to an index URL with a self-signed or expired certificate, a system clock skew invalidating cert validity, or missing root CAs on the OS.
Common situations: Corporate proxies with custom CAs not in the trust store, stale pip/distlib ca_certs, air-gapped environments, expired Let's Encrypt certs, or container images without ca-certificates installed.
Related errors
- Unexpected HTTP request on what should be a secure connectio
- Could not find a suitable TLS CA certificate bundle, invalid
- No matching distribution found for {query}
- XMLRPC request failed [code: {fault.faultCode}] {fault.fault
- proxy-connection-failed
AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04).
Data as JSON: /data/errors/74cf838e29effcb7.json.
Report an issue: GitHub.