Console9

OpenSSL: unable to get local issuer certificate

Diagnose and fix OpenSSL verify error 20 'unable to get local issuer certificate' caused by missing intermediate CA certificates.

OpenSSL produces "verify error:num=20:unable to get local issuer certificate" when the certificate chain is incomplete — the intermediate CA certificate linking the server's leaf certificate to a trusted root CA is missing.

When OpenSSL Produces This Error

OpenSSL displays "unable to get local issuer certificate" during TLS connection testing with openssl s_client -connect example.com:443. The error appears in the verification output as verify error:num=20. This same error underlies cURL error 60and browser "certificate not trusted" warnings.

What Causes "unable to get local issuer certificate" in OpenSSL

OpenSSL's certificate verification requires a complete chain from the leaf certificate to a trusted root CA. The "unable to get local issuer certificate" error occurs when one link in that chain is missing — typically the intermediate CA certificate that the server should present during the TLS handshake.

The server's web server configuration ( Nginxor Apache) must include the full certificate chain file, not just the leaf certificate. Let's Encrypt and other CAs provide a "fullchain" file that concatenates the leaf and intermediate certificates. If only the leaf certificate is configured, OpenSSL cannot complete the chain.

An outdated CA bundle on the client system also causes this error. If the root CA that signed the intermediate is not in the system's trust store, OpenSSL cannot anchor the chain. This occurs on older operating systems or minimal Docker container images that lack the ca-certificates package.

How to Fix "unable to get local issuer certificate" in OpenSSL

  1. Check which certificates the server presents using OpenSSL with the -showcerts flag:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null

Count the BEGIN CERTIFICATE blocks. One block means the intermediate is missing.

  1. Configure the web server to send the full certificate chain. In Nginx, the ssl_certificate directive must point to the fullchain file:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  1. Update the client's CA bundle if the root CA is not trusted:
sudo apt update && sudo apt install --reinstall ca-certificates
sudo update-ca-certificates

How to Verify the Fix

OpenSSL displays a verify return code of 0 after the chain is complete:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | grep "Verify return code"
Verify return code: 0 (ok)

OpenSSL: certificate has expired— occurs when a certificate in the chain has passed its validity date. OpenSSL: self-signed certificate in certificate chain— occurs when a self-signed CA that is not in the trust store appears in the chain.