Home
Articles

Common TLS certificate errors

Common TLS certificate errors

By Ibi Hasanli

·

·

4 min read

Common TLS certificate errors waste hours when a client or load balancer rejects a handshake that looked fine in the console. Most failures fall into a handful of patterns: the name does not match, the chain is incomplete, the dates are wrong, the CA is untrusted, or the wrong cert or key sits on the listener. Fix the right one and the rest of your nginx, ALB, or ACM setup usually behaves.

Hostname mismatch (CN/SAN)

Hostname mismatch means the name the client requested is not present on the certificate. Modern clients check the Subject Alternative Name (SAN) list; the Common Name alone is not enough. You see this when api.example.com hits a cert issued only for example.com, or when an internal hostname never made it into the SAN.

In nginx the wrong server_name paired with a single shared cert is a classic trap. On AWS, an ACM certificate for app.example.com will not cover app.prod.example.com unless you requested that name or a matching wildcard. Let's Encrypt will issue what you ask for; it will not invent SANs you forgot.

Incomplete certificate chain

An incomplete chain is a leaf certificate served without the intermediate(s) that link it to a trusted root. Browsers sometimes fill the gap from cache; mobile clients, Java, and curl often do not. The symptom is intermittent trust failures that look random until you compare clients.

With nginx, ssl_certificate must point at a full-chain file (leaf then intermediate), not the leaf alone. Let's Encrypt's fullchain.pem is the usual choice; cert.pem is not. ACM and many ALB listeners assemble the chain for you when the cert is managed there. But if you upload a custom cert to a network load balancer or an older appliance, you own the intermediates.

Expired or not yet valid certificate

An expired or not yet valid certificate fails date checks: notBefore is in the future or notAfter is in the past. Renewal scripts that silently fail, forgotten ACM expiry alarms, and Let's Encrypt's 90-day lifetime are the usual causes. Clock skew on the server or client produces the same error class even when the cert itself is fine.

Check both ends. I've seen an EC2 instance with a drifted clock reject a fresh ACM-backed ALB cert. openssl s_client -connect host:443 -servername host shows the dates the peer actually presents. For Let's Encrypt, confirm your renewal timer ran and that nginx was reloaded after the new files landed. A "not yet valid" error after a fresh issue often means the verifying machine's clock is behind, not that the CA misfired.

Untrusted CA or missing private CA

Untrusted CA covers self-signed certificates and private PKI whose root or intermediate is missing from the client's trust store. Internal platforms love this pattern: the cert is valid for the hostname and in date, yet every external tool and every new laptop fails until someone imports the corporate root.

AWS ACM Private CA and in-house OpenSSL CAs both need deliberate trust distribution (MDM, AMI bake, or container base images). Public browsers will never trust your private root, which is correct. Do not paper over this with curl -k in production paths; that hides every other error type too. Adding only the leaf to a Java truststore does nothing useful; you need the issuing CA.

Certificate and private key mismatch

A certificate and private key mismatch means the public key in the cert does not match the private key on the listener. Nginx fails to start or reloads with an SSL error; some load balancers accept the upload and fail at handshake time. The usual cause is rotating the cert but leaving yesterday's key, or pasting the wrong PEM into ACM or an ALB custom cert slot.

Verify with modulus or public-key comparison before you blame the CA. Wrong-cert-on-listener is the sibling failure: SNI routes shop.example.com to the marketing cert, or a default certificate answers for every name. That presents as hostname mismatch to the client even though your "correct" cert exists elsewhere on the box.

Quick Comparison

  • Error: Hostname mismatch. What you see: Name invalid / SAN error. Usual cause: Wrong CN/SAN or missing name.
  • Error: Incomplete chain. What you see: Untrusted on some clients only. Usual cause: Leaf without intermediate.
  • Error: Expired / not yet valid. What you see: Certificate has expired. Usual cause: Missed renewal or clock skew.
  • Error: Untrusted CA. What you see: Self-signed / unknown issuer. Usual cause: Private CA not in trust store.
  • Error: Key / cert mismatch. What you see: Handshake or nginx SSL error. Usual cause: Wrong key or wrong cert on listener.

Which fix do you need?

Start with what the client said, not what the dashboard claimed. Name errors mean fix SANs or SNI routing. Partial-client failures mean fix the chain file. Date errors mean renew or fix time sync. Trust errors mean distribute the CA, not disable verification. Key errors mean compare public keys before you reissue.

Most common TLS certificate errors are configuration mistakes, not CA drama. Match name, chain, dates, trust, and key, in that order, and you will clear the bulk of production TLS tickets without guessing.