"Your connection is not private" (Chrome) or "Warning: Potential Security Risk Ahead" (Firefox) is the browser refusing to complete a TLS handshake it can't verify - the exact cause is usually visible in the technical error code shown alongside the warning, and each cause has a specific, different fix. Guessing and re-issuing a certificate without checking which one you actually have wastes time.

NET::ERR_CERT_DATE_INVALID - Expired Certificate

The most common cause in production, and the most common reason it happens: automated renewal (Let's Encrypt via certbot, or a cloud load balancer's managed certificate) silently stopped working weeks earlier, and nobody noticed until the certificate actually expired.

# Check the actual expiry on the live certificate, not what a config file claims
echo | openssl s_client -connect yoursite.com:443 2>/dev/null | openssl x509 -noout -dates

# For Let's Encrypt/certbot, confirm the renewal timer is actually enabled and working
systemctl status certbot.timer
certbot renew --dry-run

Set up expiry monitoring independent of the renewal automation itself - a renewal job silently failing is exactly the failure mode that monitoring the automation from the outside catches and manual awareness doesn't.

NET::ERR_CERT_COMMON_NAME_INVALID - Domain Name Mismatch

The certificate is valid, but it doesn't cover the exact hostname being requested - a certificate issued for example.com without the www.example.com SAN entry (or vice versa), or a certificate for the wrong subdomain entirely after a DNS change.

# List every domain the certificate actually covers
echo | openssl s_client -connect yoursite.com:443 2>/dev/null | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"

Reissue the certificate with every hostname it needs to cover - both the apex domain and www, and any other subdomain actually served over the same certificate.

NET::ERR_CERT_AUTHORITY_INVALID - Untrusted or Incomplete Chain

Two different causes produce this identical browser message. The first is a genuinely self-signed certificate (expected and fine for local development, a real problem in production). The second - far more common in real production incidents - is a missing intermediate certificate: the server sent its own leaf certificate but not the intermediate CA certificate that chains it to a root the browser already trusts.

# A correctly configured server sends the FULL chain: leaf + intermediate(s)
# Verify what your server is actually sending, not just what file you configured
echo | openssl s_client -connect yoursite.com:443 -showcerts 2>/dev/null | grep -c "BEGIN CERTIFICATE"
# 1 = leaf only (broken chain). 2+ = leaf plus intermediate(s) (correct)

This specific failure mode is unusually confusing to debug because it often works fine in some browsers and fails in others - some browsers cache intermediate certificates they've seen from other sites and silently complete the chain themselves, masking a server misconfiguration that a fresh browser (or a mobile device, or a monitoring tool) will still reject.

ERR_SSL_PROTOCOL_ERROR - Serving HTTPS on the Wrong Port, or HTTP on 443

Happens most often after a reverse proxy or load balancer change - the browser connects to port 443 expecting TLS and gets a plain HTTP response instead (or vice versa on the origin server behind the proxy). Confirm what's actually listening on each port rather than assuming from a config file that hasn't been redeployed.

The Rare One: Client-Side Clock Skew

TLS certificate validation checks the current date against the certificate's validity window - a device with a badly wrong system clock (common on older hardware with a dead CMOS battery, or a freshly provisioned VM that hasn't synced NTP yet) will reject a perfectly valid certificate as not-yet-valid or expired from its own point of view. Worth checking specifically when the error is reported by one device/browser and not others hitting the identical site.

Checking This From Outside, Continuously

Every cause above except client clock skew is visible from an external check against the live certificate - and several of them (expiring soon, but not expired yet; a chain that works in some clients but not others) are much better caught before a user ever sees the warning. Shieldome checks certificate validity, expiry, and chain completeness on every scan, with alerts before a certificate actually expires. Run a free scan to check your current certificate configuration.