How to Fix SSL Certificate Errors

Troubleshoot common SSL certificate errors: expired certificates, name mismatches, untrusted issuers, mixed content, and chain issues. Step-by-step fixes.

Your site is showing an SSL error. Visitors see a scary full-page warning, and your traffic is cratering. The good news: most SSL errors come down to six common causes, and each one has a straightforward fix. Let's diagnose and resolve yours.

1. NET::ERR_CERT_DATE_INVALID (Expired Certificate)

What it looks like: "Your connection is not private" with error code NET::ERR_CERT_DATE_INVALID in Chrome, or SEC_ERROR_EXPIRED_CERTIFICATE in Firefox.

What it means: The certificate's expiry date has passed, or the certificate's start date is in the future (clock skew).

What causes it:

  • The SSL certificate genuinely expired and wasn't renewed
  • Auto-renewal failed silently (Certbot cron job broke, DNS validation failed)
  • The server's system clock is wrong (rare on servers, common on test VMs)
  • The visitor's computer clock is wrong (not your problem, but they'll blame you)

How to fix it:

1

Verify the certificate is actually expired

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null | openssl x509 -noout -dates

Check the notAfter date. If it's in the past, the cert is expired.

2

Renew the certificate

For Let's Encrypt: sudo certbot renew --force-renewal For commercial certificates: Log into your CA's portal, reissue or renew, and download the new certificate.

3

Install the new certificate

Replace the old certificate files on your web server and restart the service (sudo systemctl restart nginx or sudo systemctl restart apache2).

4

Verify the fix

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null | openssl x509 -noout -dates

Confirm the notAfter date is now in the future.

Prevent this from happening again

Set up certificate monitoring that alerts you 30, 14, and 7 days before expiry. An expired certificate is always preventable.

2. NET::ERR_CERT_COMMON_NAME_INVALID (Name Mismatch)

What it looks like: NET::ERR_CERT_COMMON_NAME_INVALID in Chrome, SSL_ERROR_BAD_CERT_DOMAIN in Firefox.

What it means: The domain you're visiting doesn't match any domain listed in the certificate's Subject Alternative Names (SANs).

What causes it:

  • Certificate was issued for example.com but you're visiting www.example.com (or vice versa)
  • A subdomain isn't included in the certificate (e.g., api.example.com not in the SANs)
  • You're accessing the site via IP address, but the certificate only covers the domain name
  • After a migration, the old certificate is still installed and doesn't cover the new domain
  • A wildcard certificate (*.example.com) doesn't cover the bare domain (example.com) or multi-level subdomains (sub.api.example.com)

How to fix it:

Check what domains the certificate actually covers:

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName

Then either:

  • Reissue the certificate with the missing domain added to the SANs
  • Use a wildcard certificate (*.example.com) if you have many subdomains
  • Fix your DNS/web server if the wrong certificate is being served (check your virtual host configuration)

3. NET::ERR_CERT_AUTHORITY_INVALID (Untrusted Issuer)

What it looks like: NET::ERR_CERT_AUTHORITY_INVALID in Chrome, SEC_ERROR_UNKNOWN_ISSUER in Firefox.

What it means: The browser doesn't trust the entity that issued the certificate.

What causes it:

  • Self-signed certificate used on a public-facing site
  • Missing intermediate certificate(s) in the chain
  • Certificate issued by a private/internal CA that isn't in the browser's trust store
  • Certificate issued by a CA that has been distrusted (rare, but it's happened -- e.g., some Symantec certificates)

How to fix it:

First, check the certificate chain:

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -showcerts </dev/null

Look at the Verify return code at the bottom. If it's 21 (unable to verify the first certificate), you're missing an intermediate.

For missing intermediates: Download the intermediate certificate from your CA's website and add it to your server configuration. In Nginx, concatenate the certificates: leaf cert first, then intermediate(s).

cat yourdomain.crt intermediate.crt > fullchain.crt

For self-signed certificates: Replace with a certificate from a trusted CA. Let's Encrypt is free and takes minutes.

For internal CAs: Distribute the root CA certificate to all client machines via group policy (enterprise) or manual installation.

4. Mixed Content Warnings

What it looks like: The padlock disappears or shows a warning icon. The page loads but the browser indicates the connection isn't fully secure. Chrome DevTools shows "Mixed Content" warnings in the Console.

What it means: The page loads over HTTPS, but some resources (images, scripts, stylesheets, iframes) are loaded over plain HTTP.

What causes it:

  • Hardcoded http:// URLs in your HTML, CSS, or JavaScript
  • Third-party resources that don't support HTTPS
  • CMS content (blog posts, product images) with absolute HTTP URLs stored in the database
  • CDN or asset pipeline serving resources over HTTP

How to fix it:

1

Find the mixed content

Open Chrome DevTools (F12), go to the Console tab, and look for "Mixed Content" warnings. They tell you exactly which resources are loaded over HTTP.

2

Update the URLs

Change http:// to https:// in your source code. Better yet, use protocol-relative URLs (//example.com/image.png) or relative paths (/image.png).

3

Add a Content-Security-Policy header

As a safety net, add Content-Security-Policy: upgrade-insecure-requests to your server's response headers. This tells browsers to automatically upgrade HTTP requests to HTTPS.

Don't wait for users to report SSL errors

Monitor your certificates and catch problems before they become outages.

5. ERR_SSL_PROTOCOL_ERROR (Protocol Mismatch)

What it looks like: ERR_SSL_PROTOCOL_ERROR in Chrome, SSL_ERROR_PROTOCOL_VERSION_ALERT in Firefox. The page doesn't load at all.

What it means: The browser and server can't agree on a TLS protocol version or cipher suite.

What causes it:

  • Server only supports outdated TLS versions (TLS 1.0, 1.1) that modern browsers have dropped
  • Server is configured with only weak cipher suites
  • TLS 1.3-only configuration on a server visited by older clients
  • Misconfigured SSL/TLS settings after a server update

How to fix it:

Check what the server supports:

# Test TLS 1.2
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -tls1_2 </dev/null 2>/dev/null

# Test TLS 1.3
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -tls1_3 </dev/null 2>/dev/null

Your server should support at least TLS 1.2 (required by all modern browsers) and ideally TLS 1.3. Update your server configuration:

Nginx:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

Apache:

SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

After changing the configuration, restart the web server and test with Qualys SSL Labs to confirm the fix.

6. Incomplete Certificate Chain

What it looks like: Works fine in Chrome and on mobile, but fails in Firefox, curl, or API clients. Some users report errors while others don't.

What it means: The server isn't sending the full certificate chain. Some clients can fill in the gaps (Chrome caches intermediates), but others can't.

What causes it:

  • Only the leaf certificate is installed, without the intermediate certificate(s)
  • The intermediates are installed in the wrong order
  • The wrong intermediate was installed (from a different CA or product)

How to fix it:

Check the chain:

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null

Look for the certificate chain in the output. You should see at least two certificates (leaf + intermediate). If you only see one, intermediates are missing.

Download the correct intermediate from your CA's documentation. Then configure your server to send the full chain:

Nginx: The ssl_certificate directive should point to a file containing the leaf cert followed by intermediate cert(s).

Apache: Use the SSLCertificateChainFile directive (Apache 2.2) or include the chain in the SSLCertificateFile (Apache 2.4+).

Verify the fix:

openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null | grep "Verify return code"

You should see Verify return code: 0 (ok).

Quick Diagnosis Table

ErrorMost Likely CauseFastest Fix
ERR_CERT_DATE_INVALIDCertificate expiredRenew and install new certificate
ERR_CERT_COMMON_NAME_INVALIDDomain not in certificate SANsReissue certificate with correct domains
ERR_CERT_AUTHORITY_INVALIDMissing intermediate or self-signedInstall intermediate certificates
Mixed ContentHTTP resources on HTTPS pageUpdate URLs to HTTPS
ERR_SSL_PROTOCOL_ERRORTLS version mismatchEnable TLS 1.2 and 1.3 on server
Works in some browsers, not othersIncomplete certificate chainAdd intermediate certificates to chain

Preventing SSL Errors

Every error on this list is preventable with monitoring. Expired certificates, chain issues, and protocol misconfigurations can all be detected before they affect your users. Set up automated checks, get alerts before things break, and keep an SSL renewal checklist so the process is never a scramble.


SSL errors are always fixable. The trick is fixing them before your visitors find them.

Never miss an SSL certificate expiry

Monitor your certificates and get alerts before they expire. Free for up to 3 certificates.