arduino/Arduino · error · CertificateError

hostname %r doesn't match %r

Error message

hostname %r doesn't match %r

What it means

ssl_match_hostname.match_hostname verifies that the hostname you connected to matches the CommonName or subjectAltName entries in the server's TLS certificate. This CertificateError is raised when the certificate is valid in form but none of its DNS names match the hostname you requested. It is urllib3's vendored copy of Python's stdlib match_hostname, called from connect() during the TLS handshake.

Source

Thrown at arduino-core/src/processing/app/i18n/python/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py:56

                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)
    if len(dnsnames) > 1:
        raise CertificateError("hostname %r "
            "doesn't match either of %s"
            % (hostname, ', '.join(map(repr, dnsnames))))
    elif len(dnsnames) == 1:
        raise CertificateError("hostname %r "
            "doesn't match %r"
            % (hostname, dnsnames[0]))
    else:
        raise CertificateError("no appropriate commonName or "
            "subjectAltName fields were found")

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Use the exact hostname listed in the certificate's subjectAltName (check with `openssl s_client -connect host:443 -servername host | openssl x509 -text | grep -A1 'Subject Alternative Name'`).
  2. Fix DNS so the correct certificate is served (SNI-aware client, correct vhost config).
  3. Reissue the certificate adding the needed SAN entry (e.g. wildcard or the www/internal name).
  4. As a last resort for trusted-but-mismatched internal endpoints, set cert_reqs='CERT_NONE' or assert_hostname to an expected value via a custom HTTPSConnectionPool — never for untrusted traffic.

Example fix

// before
import urllib3
http = urllib3.PoolManager()
r = http.request('GET', 'https://10.0.0.5/api')  # cert is for api.internal.example.com
// after
r = http.request('GET', 'https://api.internal.example.com/api')  # hostname matches cert SAN
Defensive patterns

Strategy: validation

Validate before calling

import socket
from urllib.parse import urlparse
host = urlparse(url).hostname
if host is None or _looks_like_ip(host):
    raise ValueError('Connect by the certificate hostname, not an IP: %s' % host)
def _looks_like_ip(h):
    try:
        socket.inet_aton(h)
        return True
    except socket.error:
        return False

Try / catch

from requests.exceptions import SSLError
try:
    resp = requests.get(url, timeout=10)
except SSLError as e:
    if 'doesn\'t match' in str(e):
        log.error('Hostname/cert mismatch for %s: %s', url, e)
    raise

Prevention

When it happens

Trigger: Calling urllib3/requests against https://host while the server presents a certificate whose subjectAltName/CN list contains DNS names, but none equal (or wildcard-match) the requested hostname; e.g. connecting via IP address, a CNAME alias, or 'www.example.com' when the cert only covers 'example.com'.

Common situations: Typo in the URL hostname; accessing a load balancer or internal service by IP instead of the name on the cert; server misconfigured to serve the wrong vhost/cert; SNI-less clients hitting a shared host that returns a default cert for another domain; self-signed or staging certs without the required SAN.

Related errors


AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06). Data as JSON: /api/errors/c545ce62e82d187f. Report an issue: GitHub.