Browser errors

Missing intermediate certificate: why browsers work, apps fail

By · Last verified

Error messageunable to get local issuer certificate / SEC_ERROR_UNKNOWN_ISSUER

A missing intermediate certificate means the server sends only its own certificate, not the CA certificate that connects it to a trusted root. Desktop browsers often repair this silently, so the site looks fine, while curl, mobile apps, Java and Python fail with "unable to get local issuer certificate" or similar.

Is it the site or your device?

This is always a server-side configuration problem. Confirm with the SSL checker, which does not repair chains:

curl ssl.sh/example.com

If the result says "chain incomplete", the server must be fixed. Visitors and app users cannot fix it safely; installing the intermediate on one device only hides the problem.

Causes

1. Configured the leaf file instead of the full chain

Pointing the server at the leaf file instead of the full chain is the most common case. With Let's Encrypt, cert.pem is the leaf and fullchain.pem is leaf plus intermediates. Using cert.pem in ssl_certificate drops the intermediate. Check what the server sends:

openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
  | grep -c "BEGIN CERTIFICATE"

A result of 1 means only the leaf is sent.

2. Commercial certificate installed without its CA bundle

CAs deliver the leaf and a separate "CA bundle" or "intermediate" file. Apache before 2.4.8 used SSLCertificateChainFile for it; Nginx needs the files concatenated.

3. Wrong or outdated intermediate

The bundle belongs to a different product line or an old intermediate that no longer signed your certificate. The chain looks complete but does not link up. Compare the leaf's issuer with the intermediate's subject.

4. Panel or CDN upload left out the chain

Many control panels have separate fields for the certificate and the chain, or expect both in one box. Pasting only the first block drops the intermediate.

What it looks like in each browser

Client Behaviour with a missing intermediate
Chrome / Edge / Safari Usually works, because the browser downloads the intermediate via AIA
Firefox Works for public CAs thanks to preloaded intermediates; fails with SEC_ERROR_UNKNOWN_ISSUER for others
Android apps Trust anchor for certification path not found (details)
curl / OpenSSL unable to get local issuer certificate (details)
Java PKIX path building failed
Python CERTIFICATE_VERIFY_FAILED

How site owners fix it

Serving the leaf plus every intermediate, in order, fixes it for all clients.

1. Use the full-chain file. Nginx:

ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

2. For commercial certificates, concatenate in order:

cat example.com.crt ca-bundle.crt > example.com.fullchain.crt

Apache 2.4.8 and later read the chain from SSLCertificateFile, so point it at the same combined file.

3. If you are unsure which intermediate you need, paste your leaf into the chain builder; it fetches the correct intermediates and outputs the bundle in the right order.

4. Verify with a strict client. Run curl ssl.sh/example.com and curl -I https://example.com from a machine without browser caches. Both must succeed before you consider it fixed. See certificate chains for background.

FAQ

Why does my site work in Chrome but not in my mobile app?

Chrome fetches the missing intermediate on its own using the AIA extension. Most app HTTP libraries do not, so they cannot complete the chain. Serve the intermediates from the server and both will work.

Should I include the root certificate in the chain?

No. Clients already have the root in their trust store; sending it wastes bytes and can confuse some clients. Send the leaf followed by the intermediates only.

In what order should the certificates be in the file?

The server's own certificate first, then the intermediate that signed it, then any higher intermediate. TLS 1.3 tolerates other orders, but older clients may not.

Is this a visitor problem I can fix on my device?

No. Installing intermediates locally only hides the server's mistake on one device. The site owner must send the full chain.

Sources

  1. RFC 8446 section 4.4.2: Certificate message
  2. Mozilla Wiki: Intermediate preloading
  3. Let's Encrypt: Chains of trust
  4. nginx ngx_http_ssl_module: ssl_certificate