Error message
verify error:num=19:self-signed certificate in certificate chain
Also printed as
- verify error:num=19:self signed certificate in certificate chain
- error 19 at 2 depth lookup: self-signed certificate in certificate chain
OpenSSL 3.x prints "self-signed", 1.1.1 "self signed". openssl verify reports it as "error 19 at <depth> depth lookup: …", where the depth is the root's position in the chain.
OpenSSL CLI (openssl s_client / openssl verify) — X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
What it means
OpenSSL error 19 (X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN): the chain was built all the way up to a self-signed root certificate that came from the peer, and that root is not in the trusted store. Unlike error 18, there is a real CA hierarchy; unlike error 20, nothing is missing. The root must be trusted locally, or the connection is being intercepted.
Why it happens
A TLS-inspecting proxy
commonCorporate proxies send their own root in the chain. If the subject of the top certificate names your company or a security vendor, the connection is inspected.
A private CA whose root is sent by the server
commonInternal services often send the full chain including the root; clients still need the root installed as a trust anchor.
The test ran without the expected trust store
occasionalTesting with -CAfile pointing at the wrong file, or in an image whose store lacks the company root, produces this code for a correctly configured internal service.
How to fix it
- 1.
Identify the root and its fingerprint
Split the served chain and print subject, issuer and SHA-256 fingerprint of each certificate; compare the root's fingerprint with the one your IT or PKI team publishes.
bash openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | awk '/BEGIN CERT/{n++} {print > ("cert" n ".pem")}' for f in cert[0-9]*.pem; do openssl x509 -in "$f" -noout -subject -issuer -fingerprint -sha256 2>/dev/null; done - 2.
Test with, then install, the correct root
If -CAfile with the published root gives "Verify return code: 0 (ok)", install that root into the system store.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com \ -CAfile corp-root-ca.pem 2>&1 | grep 'Verify return code' sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt && sudo update-ca-certificates - 3.
Server owners: send leaf and intermediates only
Sending the root wastes bytes in every handshake and never makes it trusted; distribute the root to clients instead.
bash # Server owners: the root does not belong in the served chain cat server.pem intermediate.pem > fullchain.pem
Related errors
verify error:num=18:self-signed certificateOpenSSL CLI (openssl s_client / openssl verify)verify error:num=20:unable to get local issuer certificateOpenSSL CLI (openssl s_client / openssl verify)curl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)self-signed certificate in certificate chainNode.js tls / https / fetch