arduino/Arduino · error · ValueError
empty or no certificate
Error message
empty or no certificate
What it means
ssl_match_hostname.match_hostname() raises ValueError('empty or no certificate') when the cert argument is falsy — None or an empty dict. A peer certificate dict (typically from SSLSocket.getpeercert()) is required to perform hostname verification; without it there is nothing to match against.
Source
Thrown at arduino-core/src/processing/app/i18n/python/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py:32
# When '*' is a fragment by itself, it matches a non-empty dotless
# fragment.
pats.append('[^.]+')
else:
# Otherwise, '*' matches any dotless fragment.
frag = re.escape(frag)
pats.append(frag.replace(r'\*', '[^.]*'))
return re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
def match_hostname(cert, hostname):
"""Verify that *cert* (in decoded format as returned by
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 rules
are mostly followed, but IP addresses are not accepted for *hostname*.
CertificateError is raised on failure. On success, the function
returns nothing.
"""
if not cert:
raise ValueError("empty or no certificate")
dnsnames = []
san = cert.get('subjectAltName', ())
for key, value in san:
if key == 'DNS':
if _dnsname_to_pat(value).match(hostname):
return
dnsnames.append(value)
if not dnsnames:
# The subject is only checked when there is no dNSName entry
# in subjectAltName
for sub in cert.get('subject', ()):
for key, value in sub:
# XXX according to RFC 2818, the most specific Common Name
# must be used.
if key == 'commonName':
if _dnsname_to_pat(value).match(hostname):
return
dnsnames.append(value)View on GitHub (pinned to a0df6e0e83)
Solutions
- Check `if not cert:` before calling match_hostname and treat it as a failed/handshake-unverified connection.
- Configure the SSL context with CERT_REQUIRED so a peer certificate is always present.
- Pass the parsed dict from getpeercert(), not the socket or raw PEM bytes.
- Reject connections lacking a certificate rather than proceeding unverified.
Example fix
// before
match_hostname(sock.getpeercert(), hostname)
// after
cert = sock.getpeercert()
if not cert:
raise SSLError('no peer certificate presented')
match_hostname(cert, hostname) Defensive patterns
Strategy: validation
Validate before calling
cert = sock.getpeercert()
if not cert:
raise SSLError('peer presented no certificate')
match_hostname(cert, hostname) Type guard
def has_peer_certificate(cert):
return isinstance(cert, dict) and len(cert) > 0 Try / catch
try:
match_hostname(cert, hostname)
except ValueError as e:
if 'empty or no certificate' in str(e):
raise SSLError('no certificate to verify') from e
raise Prevention
- Always configure CERT_REQUIRED so getpeercert() returns a populated dict.
- Falsiness-check the cert dict before verification and abort on empty.
- Pass the parsed cert dict, never the socket or raw bytes.
When it happens
Trigger: Calling match_hostname(sock.getpeercert(), hostname) when the peer sent no certificate (getpeercert() returns None on unauthenticated sessions) or an empty dict; passing the raw socket instead of the cert dict.
Common situations: TLS sessions negotiated without certificate verification or with anonymous cipher suites; forgetting to enable CERT_REQUIRED so the peer cert is never populated; testing harnesses with mock sockets returning None.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- hostname %r doesn't match either of %s
- SSLError(e)
- Can't connect to HTTPS URL because the SSL module is not ava
- hostname %r doesn't match %r
- no appropriate commonName or subjectAltName fields were foun
AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06).
Data as JSON: /api/errors/5b9b6c49f0ad7425.
Report an issue: GitHub.