Guides

SSL/TLS and certificate errors

TLS errors come from one of two phases: the handshake (protocol and cipher negotiation) or certificate validation (is this really the server I asked for?). Validation errors are the common ones, and every one of them has a correct fix that is not "turn verification off."

The validation failures

CERT_HAS_EXPIREDPast its notAfter date. Renewals didn't run — or a machine's clock is wrong, which produces the same error with a valid cert.
SELF_SIGNED_CERT_IN_CHAIN / DEPTH_ZERO_SELF_SIGNED_CERTThe chain ends in a certificate your trust store doesn't contain — internal CA, corporate TLS-inspecting proxy, or a genuinely self-signed dev cert.
UNABLE_TO_VERIFY_LEAF_SIGNATUREThe server sent its leaf certificate but not the intermediate — browsers paper over this (AIA fetching), CLI tools and libraries do not.
ERR_TLS_CERT_ALTNAME_INVALID / hostname mismatchValid certificate, wrong name: the cert's SANs don't include the hostname you dialed. Connecting by IP, by internal alias, or SNI misrouting on shared hosting.
Handshake failure / protocol versionNo overlap in TLS versions or ciphers — typically an old client (TLS 1.0/1.1) against a modern server, or vice versa.

See what the server actually serves

openssl s_client -connect api.example.com:443 -servername api.example.com | \
  openssl x509 -noout -dates -subject -ext subjectAltName

That one command answers most tickets: the real expiry dates, the names the cert covers, and (in the full s_client output) whether the intermediate is in the served chain. Compare against what your code dials — including the port and the exact hostname, since SNI means different names can get different certificates from the same IP.

Fix the trust, don't disable it

NODE_TLS_REJECT_UNAUTHORIZED=0, verify=False, InsecureSkipVerify: true — every stack has the same trapdoor, and it turns "TLS error in staging" into "silent man-in-the-middle in production" the day the snippet gets copied. The correct moves: renew (and automate renewal), add your internal CA to the trust store (NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE, SSL_CERT_FILE, or the OS store), serve the full chain from the server, and dial the name the certificate is actually for. Scope any dev-only exception to a single explicit host, never process-wide.

Documented occurrences

116 analyzed errors across 26 libraries match this failure class. Each links to the thrown message, its source line, and documented fixes.

redis/redis-py

guzzle/guzzle

docker/cli

jackc/pgx

urllib3/urllib3

celery/celery

redis/redis

gofiber/fiber

aio-libs/aiohttp

gohugoio/hugo

…and 16 more libraries — search for your exact message.

Other failure classes