The TLS handshake failed because a server presented a certificate that the client no longer considered valid due to its expiration date.

This most commonly happens because the certificate on the server has genuinely expired and needs to be renewed. The server’s TLS/SSL configuration might be pointing to an old, expired certificate file instead of the newly generated one. If you’re using a certificate management system (like cert-manager in Kubernetes or a cloud provider’s certificate service), that system might have failed to automatically renew the certificate, or the renewal process itself encountered an error. Network intermediaries, such as load balancers or reverse proxies, might be caching an expired certificate and presenting it to clients even if the backend server has a valid, renewed certificate. The system’s clock on either the client or server might be significantly out of sync, leading to a misinterpretation of the certificate’s validity period. Finally, the certificate was correctly renewed, but the web server or application service was not restarted or reloaded to pick up the new certificate.

Diagnosis and Fixes:

  1. Server Certificate Expiration:

    • Diagnosis: On the server, check the certificate file’s expiration date. For OpenSSL, use:
      openssl x509 -in /path/to/your/certificate.crt -noout -enddate
      
      If the output shows a date in the past, the certificate has expired.
    • Fix: Obtain a new certificate from your Certificate Authority (CA) and replace the expired file on the server. Then, configure your web server (e.g., Nginx, Apache) or application to use the new certificate. For Nginx, this would involve updating the ssl_certificate and ssl_certificate_key directives in your nginx.conf or site-specific configuration file, followed by a reload:
      # Example Nginx configuration snippet
      ssl_certificate /etc/ssl/certs/your_new_domain.crt;
      ssl_certificate_key /etc/ssl/private/your_new_domain.key;
      
      sudo systemctl reload nginx
      
    • Why it works: This directly replaces the invalid certificate with a valid, current one, satisfying the TLS handshake requirement.
  2. Incorrect Certificate File Path:

    • Diagnosis: Review your web server or application’s TLS/SSL configuration to ensure the paths to the certificate and private key files are correct and point to the newly renewed files, not old ones.
    • Fix: Edit the configuration file to correct the file paths. For example, in Apache’s ssl.conf or virtual host configuration:
      SSLCertificateFile /etc/ssl/certs/your_new_domain.crt
      SSLCertificateKeyFile /etc/ssl/private/your_new_domain.key
      
      Then reload the service:
      sudo systemctl reload apache2
      
    • Why it works: The server was likely configured to use the correct name for the new certificate, but the actual file at that location was still the old, expired one. Correcting the path or ensuring the new file is at the expected location resolves this.
  3. Certificate Renewal System Failure:

    • Diagnosis: If using an automated system like cert-manager in Kubernetes, check its logs for errors related to certificate issuance or renewal. For example, in Kubernetes:
      kubectl logs -n cert-manager <cert-manager-pod-name>
      
      Also, check the status of the Certificate resource:
      kubectl describe certificate <your-certificate-name> -n <your-namespace>
      
      Look for events indicating failure to obtain or renew.
    • Fix: Address the specific error indicated in the logs. This might involve fixing DNS challenges (e.g., ensuring _acme-challenge TXT records are correctly propagated), resolving API rate limits with the CA, or ensuring the Issuer or ClusterIssuer is correctly configured. For a DNS challenge issue, you might need to update your DNS provider’s configuration.
    • Why it works: Automated renewal systems fail for specific reasons. Diagnosing and fixing the root cause (DNS, API, configuration) allows the system to successfully obtain a new certificate.
  4. Proxy/Load Balancer Caching:

    • Diagnosis: If a load balancer or reverse proxy sits in front of your application server, it might be terminating TLS and presenting its own certificate. Check the certificate presented by the proxy, not just the backend server. You can use openssl s_client pointed at the proxy’s IP/hostname:
      openssl s_client -connect your.proxy.domain.com:443 -servername your.proxy.domain.com
      
      Examine the certificate details in the output.
    • Fix: Renew or update the certificate on the proxy/load balancer. If it’s a managed service (e.g., AWS ELB, GCP Load Balancer), update the certificate associated with the listener. If it’s a self-hosted proxy like HAProxy or Traefik, update its configuration and reload it.
      # Example for updating an AWS ACM certificate on an ELB
      # This is done via the AWS Console or AWS CLI, not a direct command.
      # Ensure the ARN of the renewed certificate is associated with the HTTPS listener.
      
    • Why it works: Proxies often cache TLS connections and presented certificates. Updating the certificate on the proxy ensures it presents a valid certificate to clients.
  5. System Clock Skew:

    • Diagnosis: Check the current date and time on both the client machine attempting to connect and the server machine hosting the certificate.
      date
      
      If the time is off by more than a few minutes (or longer, depending on the CA’s tolerance), it can cause expiration issues.
    • Fix: Synchronize the system clocks using NTP. On Linux servers:
      sudo apt update && sudo apt install ntp
      sudo systemctl enable ntp
      sudo systemctl start ntp
      # Or for systemd-timesyncd:
      sudo timedatectl set-ntp true
      
      Ensure clients also have their clocks synchronized.
    • Why it works: TLS certificate validation relies on accurate timestamps. Synchronizing clocks ensures the server’s certificate is evaluated against the correct current time.
  6. Service Not Reloaded After Update:

    • Diagnosis: Even if the certificate file is updated and the configuration points to it, the web server process might still be running with the old certificate loaded in memory. This is often indicated by the certificate appearing valid in file system checks but still expiring in browser/client checks.
    • Fix: Perform a graceful reload or restart of the web server or application service.
      # For Nginx
      sudo systemctl reload nginx
      
      # For Apache
      sudo systemctl reload apache2
      
      # For systemd services in general
      sudo systemctl restart your-service-name.service
      
    • Why it works: Reloading the service forces it to re-read its configuration and load the new certificate from disk into memory, replacing the old, expired one.

The next error you’ll likely encounter if you fix this is a TLS Alert unknown_ca if the new certificate was issued by an intermediate CA that your clients don’t trust, or if the certificate chain is incomplete.

Want structured learning?

Take the full Tls-ssl course →