← Back to Blog

7 Common SSL/TLS Errors and How to Fix Them

SSL/TLS · June 11, 2026 · 13 min read

SSL certificate errors bring production sites down with cryptic browser warnings. This guide covers the seven most common SSL/TLS errors — name mismatches, expired certs, incomplete chains, mixed content, protocol mismatches, revoked certificates, and weak ciphers — with step-by-step fixes for each.

Technical cover image for 7 Common SSL/TLS Errors and How to Fix Them

1. Certificate Name Mismatch (ERR_CERT_COMMON_NAME_INVALID)

The domain name in the browser's address bar does not match any name in the certificate's Common Name or Subject Alternative Name fields. This is the single most common SSL error in production.

Common causes:

  • The certificate covers www.example.com but users visit example.com (or vice versa)
  • A wildcard cert for *.example.com does not cover the bare domain example.com
  • An internal hostname (server.local) is being accessed externally
  • The certificate was issued for a different domain entirely after a migration

How to fix it:

First, identify exactly what names your certificate covers. Use the SSL Certificate Decoder to see the full SAN list:

# Check the SAN list from your live server
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -text | grep -A1 "Subject Alternative"

# Or decode a certificate file directly
openssl x509 -in certificate.crt -text -noout | grep -A1 "Subject Alternative"

If the bare domain is missing from a wildcard cert: reissue the certificate and explicitly include the base domain as a SAN. Most CAs add it automatically, but if yours didn't, you need to request it.

If www and non-www diverge: either issue a certificate with both names as SANs, or choose one canonical form and set up a permanent HTTP redirect from the other. The second approach is cleaner for SEO. Run the SSL Checker against both versions of the domain to confirm both are handled correctly.

2. Expired Certificate (ERR_CERT_DATE_INVALID)

The certificate's validity period has ended. Browsers block the connection with no override that a non-technical user can navigate. This error is entirely preventable — and yet it happens constantly.

Why expired certificates still happen in 2026:

  • Auto-renewal broke silently. Let's Encrypt certbot renewal cron job failed because of a DNS plugin error, a firewall rule change, or an expired API token — and nobody noticed for 60 days.
  • The certificate was deployed manually once. Nobody documented the renewal process. The original engineer left. Nobody knew it expired until the site went down.
  • A load balancer or CDN terminated TLS with the old certificate while the origin server had the new one. Partial deployment.
  • The system clock is wrong. The certificate is valid, but the server's clock drifted far enough that it thinks the cert is expired. Check with date and timedatectl.

How to fix it:

# Check certificate expiry from the live endpoint
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -dates

# Check expiry of a local certificate file
openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -enddate

# For Let's Encrypt, check certbot timer status
systemctl status certbot.timer
certbot certificates

Immediate fix: renew the certificate. For Let's Encrypt, certbot renew --force-renewal and reload the web server. For commercial CAs, reissue from the provider's dashboard.

Long-term fix: set up monitoring. The SSL Checker shows days remaining on any certificate. Set up alerts at 30, 14, and 7 days before expiry. For Let's Encrypt, verify that certbot.timer is enabled and running — systemctl list-timers | grep certbot should show the next run. Test renewal manually: certbot renew --dry-run.

3. Incomplete Certificate Chain (ERR_CERT_AUTHORITY_INVALID)

The server sent its leaf certificate but did not include one or more intermediate certificates required to build a chain of trust back to a root CA in the browser's trust store. Desktop browsers sometimes cache intermediates and mask this error — mobile browsers and API clients (curl, Python requests) do not. This makes it one of the hardest errors to reproduce.

How to detect it:

# The definitive test — run from a machine without cached intermediates
openssl s_client -connect example.com:443 -showcerts 2>/dev/null | grep "verify error"

# Check the chain on your live server
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null \
  | openssl verify -verify_return_error 2>&1

# Use the TLS Scanner for a comprehensive chain analysis
# It tests from multiple vantage points and catches partial chain issues

How to fix it:

For Nginx: concatenate your certificate with the intermediate bundle. The file specified in ssl_certificate should contain your server certificate followed by all intermediate CA certificates in order, from leaf to root:

# Concatenate in correct order (server cert first, then intermediates)
cat server.crt intermediate1.crt intermediate2.crt > /etc/nginx/ssl/chain.pem

# nginx config
ssl_certificate     /etc/nginx/ssl/chain.pem;
ssl_certificate_key /etc/nginx/ssl/private.key;

For Apache: use the SSLCertificateChainFile directive (Apache 2.4.8+) or concatenate the intermediates into the certificate file. After fixing, test with the TLS Scanner — it will flag incomplete chains and missing intermediates that browsers and mobile clients might miss.

4. Mixed Content Warnings

The page loads over HTTPS, but some resources (images, scripts, stylesheets, iframes, XHR requests) are loaded over HTTP. Modern browsers block active mixed content (scripts, XHR) by default and show warnings for passive mixed content (images, video). Users see a broken padlock — or a completely broken page.

Where mixed content hides:

  • Hardcoded HTTP URLs in templates, CMS content, or database records (http://cdn.example.com/logo.png)
  • Third-party embeds — analytics scripts, ad networks, social media widgets loading over HTTP
  • Reverse proxy config — the proxy serves HTTPS to the browser but fetches upstream content over HTTP, and the HTML contains absolute HTTP URLs
  • CSS url() references — background images and fonts loaded with hardcoded http:// URLs
  • 301 redirects — the browser follows an HTTP→HTTPS redirect for a resource, but the initial request was HTTP

How to fix it:

Quick wins: use protocol-relative URLs (//cdn.example.com/logo.png) or upgrade all resource URLs to HTTPS. Add the Content-Security-Policy: upgrade-insecure-requests header to automatically upgrade HTTP requests to HTTPS at the browser level — this is a one-line fix that catches most mixed content issues:

# Nginx: add this inside the server block
add_header Content-Security-Policy "upgrade-insecure-requests";

# Apache (.htaccess or virtual host)
Header always set Content-Security-Policy "upgrade-insecure-requests"

Deep fix: audit your site with browser DevTools (Console and Network tabs filter for mixed content warnings), then update every hardcoded URL. For CMS-driven sites, run a database search for http:// in content fields and replace with https://. Use the SSL Checker to verify the padlock status after changes.

5. Protocol Version Mismatch (ERR_SSL_VERSION_OR_CIPHER_MISMATCH)

The client and server cannot agree on a TLS protocol version or cipher suite. This error increased dramatically after TLS 1.0 and 1.1 were deprecated (RFC 8996, March 2021) and as older clients continue to exist in the wild.

SymptomLikely CauseFix
Older Android devices (4.x, 5.x) cannot connect Server requires TLS 1.3, device only supports up to TLS 1.2 Enable TLS 1.2 alongside TLS 1.3: ssl_protocols TLSv1.2 TLSv1.3;
Windows XP / IE 8 users cannot connect Server disabled TLS 1.0 and 1.1 (correctly). These clients are obsolete Do not downgrade. These clients are insecure and unsupported. Direct users to upgrade
API clients (curl, Python) fail but browsers work Client library linked against old OpenSSL without TLS 1.3 or modern cipher support Update the client library. Alternatively, enable a broader cipher set on the server
Connection works on one server but not another behind same load balancer Different backend servers have different TLS configurations Standardize TLS config across all backends. Use configuration management

How to diagnose:

# Test which TLS versions a server supports
openssl s_client -connect example.com:443 -tls1_2 2>/dev/null | grep "Verification"
openssl s_client -connect example.com:443 -tls1_3 2>/dev/null | grep "Verification"

# Comprehensive protocol and cipher scan
nmap --script ssl-enum-ciphers -p 443 example.com

# Use the TLS Scanner for a detailed breakdown
# It tests every protocol version and cipher suite combination

Recommended baseline for 2026: enable TLS 1.2 and TLS 1.3. Disable TLS 1.0 and 1.1. Use the TLS Scanner to see exactly which protocols and ciphers your server advertises. If you see TLS 1.0 or 1.1 enabled, disable them immediately unless you have a documented legacy client requirement — and even then, plan the migration.

6. Revoked Certificate (ERR_CERT_REVOKED)

The certificate was revoked by the issuing CA — typically because the private key was compromised, the certificate was issued fraudulently, or the domain ownership changed. Browsers that check OCSP or CRLs will block the connection; browsers that don't (or cache OCSP responses) may not — making this error inconsistent across users.

Steps to resolve:

  1. Confirm the revocation. Check the certificate against OCSP:
    openssl s_client -connect example.com:443 -status 2>/dev/null | grep -A20 "OCSP"
  2. If the key was compromised: revoke is correct. Generate a new private key and certificate. Do not reuse the old key. Audit all systems that had access to the compromised key.
  3. If the revocation was a mistake: contact your CA. Some CAs allow un-revocation within a short window. Most do not. You will likely need a new certificate.
  4. Replace the certificate everywhere. A revoked certificate on a load balancer that you forgot about still blocks users.

Prevention: use Certificate Transparency monitoring (which Let's Encrypt and most public CAs log to) to detect unauthorized certificates issued for your domains. Services like crt.sh let you search CT logs for any certificate containing your domain name. If you see one you didn't request, contact the CA immediately.

7. Weak Cipher Suites and HSTS Misconfiguration

This is two related problems that often appear together. Weak cipher suites (RC4, 3DES, export-grade ciphers, NULL ciphers) allow downgrade attacks and are flagged by security scanners and compliance audits. HSTS (HTTP Strict Transport Security) misconfiguration breaks sites when the HSTS policy is too broad or the certificate chain has issues.

Weak cipher detection and remediation:

# Test cipher suites with nmap
nmap --script ssl-enum-ciphers -p 443 example.com | grep -E "weak|broken|LOW|NULL|RC4|3DES"

# Modern Nginx cipher configuration (2026 baseline)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;  # Let client choose among strong ciphers
ssl_ecdh_curve X25519:prime256v1:secp384r1;

Common HSTS mistakes that break sites:

  • Setting includeSubDomains before all subdomains have valid HTTPS. Once the browser receives this header, it refuses HTTP connections to all subdomains — including ones that don't exist yet. Any subdomain without valid HTTPS becomes unreachable.
  • Setting a long max-age during testing. Start with max-age=300 (5 minutes). Only increase to the standard 31536000 (1 year) after confirming HTTPS works on every subdomain.
  • Forgetting about internal tools. jenkins.internal.example.com or grafana.internal.example.com may use self-signed certificates. HSTS with includeSubDomains will block them. Exclude internal subdomains from the certificate's scope or don't use includeSubDomains.

Safe HSTS rollout:

# Phase 1: Test with a short TTL and no subdomains
add_header Strict-Transport-Security "max-age=300";

# Phase 2: Extend to subdomains after verifying all have valid HTTPS
add_header Strict-Transport-Security "max-age=300; includeSubDomains";

# Phase 3: After 1-2 weeks of monitoring, go to production max-age
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

Use the TLS Scanner to verify your cipher suite configuration and HSTS header across all subdomains. It checks protocol versions, cipher strength, certificate validity, and HSTS headers in a single report.

SSL Error Diagnostic Workflow

When an SSL error is reported, use this order of operations to find the root cause quickly:

  1. Reproduce the exact error. Open the browser DevTools → Security tab. Note the exact error code (e.g., ERR_CERT_DATE_INVALID). The generic "Your connection is not private" message has a specific error code buried in the details.
  2. Run the SSL Checker. This gives you certificate expiry, chain validity, and protocol support in one view. It catches 80% of SSL issues before you need to open a terminal.
  3. Decode the certificate. Use the SSL Decoder to inspect the SAN list, validity dates, issuer chain, key size, and signature algorithm. Compare what the certificate claims against what you expect.
  4. Scan for protocol and cipher issues. The TLS Scanner tests every protocol version and cipher suite combination. This catches the cases where the certificate is valid but the TLS configuration is broken.
  5. Check from multiple vantage points. A certificate that works from your office might fail from a mobile network or a different country. CDNs and anycast DNS mean different users hit different servers. Test from multiple locations when possible.
  6. Check the system clock. date and timedatectl. A drift of even a few hours can cause certificate validation failures. This is especially common on VMs that were paused and resumed, or bare-metal servers with dead CMOS batteries.

Related SSL/TLS Tools

  • SSL Certificate Checker — Verify certificate validity, expiry, chain trust, and protocol support. Catch expiring certificates and chain issues before they cause outages.
  • TLS Scanner — Comprehensive TLS configuration scan — protocol versions, cipher suites, HSTS headers, certificate transparency, and vulnerability checks in one report.
  • SSL Certificate Decoder — Decode any X.509 certificate to inspect SANs, validity dates, issuer, key size, signature algorithm, and all extensions. Paste a PEM or fetch from a live server.

Frequently Asked Questions

Different browsers use different certificate stores and validation logic. Chrome uses the operating system's trust store on most platforms, while Firefox uses its own (NSS). If an intermediate certificate is cached by the OS but not by Firefox, the chain will validate in Chrome but fail in Firefox. This is almost always an incomplete certificate chain issue. Fix the chain on the server — don't rely on browser-side caching. Use the SSL Checker to test the chain from an independent perspective.

Set up an internal CA and distribute the root certificate to all client machines via group policy (Windows) or MDM (macOS, iOS, Android). For small deployments, self-signed certificates with manual trust installation work but don't scale. If the internal server has a publicly resolvable domain name, you can use Let's Encrypt with DNS-01 validation even for internal servers — the validation only requires DNS record creation, not public HTTP access.

Yes. SSL certificates are not bound to a specific server or IP address — they validate domain names, not machines. You can deploy the same certificate and private key across multiple servers (load balancers, CDN edge nodes, application servers) as long as they all serve the same domain names. The security consideration is that the private key now exists in multiple places, increasing the attack surface. Use per-server certificates (each with its own key) when possible to limit the blast radius of a key compromise.