fjordtools / Errors / unable to get local issuer

unable to get local issuer certificate

A client checks a certificate by following its issuers up to a root it already trusts. This error means one link was missing: the server did not send an intermediate, or the issuer is not in the client's trusted store. The usual cause is a server that sends only its own certificate.

Fjordtools team · Seen in OpenSSL, curl, Node and Python · Published · 2 min read

How the tools word it

OpenSSL 3.6 s_clientverify error:num=20:unable to get local issuer certificate
OpenSSL 3.6 verifyerror 20 at 1 depth lookup: unable to get local issuer certificate
curl 8.23curl: (60) SSL certificate OpenSSL verify result: unable to get local issuer certificate (20)
Node 26 tlsUNABLE_TO_VERIFY_LEAF_SIGNATURE: unable to verify the first certificate
Python 3.14 sslssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1082)

Common causes

  1. The server did not send its intermediate certificate

    The certificate names its issuer, but the issuer's own certificate was not sent with it, so the chain has a gap. Some browsers fill such a gap themselves, which is why a site can open in a browser and still fail in curl, Node or Python. If the certificate lists a CA issuers address, the Decoder shows it.

    Input

    -----BEGIN CERTIFICATE-----
    MIIB7jCCAZWgAwIBAgIBBDAKBggqhkjOPQQDAjBBMRgwFgYDVQQKDA9mam9yZHRv
    b2xzIHRlc3QxJTAjBgNVBAMMHGZqb3JkdG9vbHMgdGVzdCBpbnRlcm1lZGlhdGUw
    HhcNMjYwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjAwMRgwFgYDVQQKDA9mam9y
    ZHRvb2xzIHRlc3QxFDASBgNVBAMMC3NlcnZlci50ZXN0MFkwEwYHKoZIzj0CAQYI
    KoZIzj0DAQcDQgAE7ee19O78yqmyOB5x/h4K7/QA6YW32XJesJT8lv2Q+Y0GBR4e
    r2DpKzlXcNQ5G7VN9GkztuzSnXch/wKr38FQdqOBjjCBizAMBgNVHRMBAf8EAjAA
    MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAWBgNVHREEDzAN
    ggtzZXJ2ZXIudGVzdDAdBgNVHQ4EFgQU/HjqRgLgUEQQDnr1y8nhCcb2baowHwYD
    VR0jBBgwFoAUMt7RDnv6EJHcKso7bd3VWZC9krowCgYIKoZIzj0EAwIDRwAwRAIg
    VatubrykL+ZDu2wIXIFzNCA4G6SIsUQnf2mw4c30KXMCICf1jBo0UciVihHiS1KE
    k6cc1SY9pCBuOPjwOoiC3ob3
    -----END CERTIFICATE-----

    Certificate Decoder says

    Issuer · CN=fjordtools test intermediate,O=fjordtools test
  2. The chain you pasted has a gap

    Paste what the server sends. The Decoder links certificates by name and key ID. A leaf followed by the root, with the intermediate missing, shows issuer not in the input on the leaf. The intermediate belongs between them.

    Input

    -----BEGIN CERTIFICATE-----
    MIIB7jCCAZWgAwIBAgIBBDAKBggqhkjOPQQDAjBBMRgwFgYDVQQKDA9mam9yZHRv
    b2xzIHRlc3QxJTAjBgNVBAMMHGZqb3JkdG9vbHMgdGVzdCBpbnRlcm1lZGlhdGUw
    HhcNMjYwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjAwMRgwFgYDVQQKDA9mam9y
    ZHRvb2xzIHRlc3QxFDASBgNVBAMMC3NlcnZlci50ZXN0MFkwEwYHKoZIzj0CAQYI
    KoZIzj0DAQcDQgAE7ee19O78yqmyOB5x/h4K7/QA6YW32XJesJT8lv2Q+Y0GBR4e
    r2DpKzlXcNQ5G7VN9GkztuzSnXch/wKr38FQdqOBjjCBizAMBgNVHRMBAf8EAjAA
    MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAWBgNVHREEDzAN
    ggtzZXJ2ZXIudGVzdDAdBgNVHQ4EFgQU/HjqRgLgUEQQDnr1y8nhCcb2baowHwYD
    VR0jBBgwFoAUMt7RDnv6EJHcKso7bd3VWZC9krowCgYIKoZIzj0EAwIDRwAwRAIg
    VatubrykL+ZDu2wIXIFzNCA4G6SIsUQnf2mw4c30KXMCICf1jBo0UciVihHiS1KE
    k6cc1SY9pCBuOPjwOoiC3ob3
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    MIIBwzCCAWqgAwIBAgIBATAKBggqhkjOPQQDAjA5MRgwFgYDVQQKDA9mam9yZHRv
    b2xzIHRlc3QxHTAbBgNVBAMMFGZqb3JkdG9vbHMgdGVzdCByb290MB4XDTI2MDEw
    MTAwMDAwMFoXDTM2MDEwMTAwMDAwMFowOTEYMBYGA1UECgwPZmpvcmR0b29scyB0
    ZXN0MR0wGwYDVQQDDBRmam9yZHRvb2xzIHRlc3Qgcm9vdDBZMBMGByqGSM49AgEG
    CCqGSM49AwEHA0IABH0DdyM4j2Qm5yUYrP9opJIyAW5oKmYs1KlgD5QaEspetzDt
    LmYCaEdSk051mmCgtov0ROqWiElrHplTLeJ0vQWjYzBhMB8GA1UdIwQYMBaAFLcg
    9Ms28bssX2hEC2iuZ/lj9P4oMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
    AgEGMB0GA1UdDgQWBBS3IPTLNvG7LF9oRAtormf5Y/T+KDAKBggqhkjOPQQDAgNH
    ADBEAiBJvWgbvsYiq9JtmZfKyepnmBnyzFQ93G+Tu9MHiZSt9wIgLz6fgDWJkUSD
    djhBBe3H4vsZwwTf+tNiFatZWY+Bkno=
    -----END CERTIFICATE-----

    Certificate Decoder says

    leaf · issuer not in the input
    root · self-signed
  3. The client does not know the root

    Here the server did its part: the leaf and the intermediate. Only the root is missing, and it must come from the client's own trust store. OpenSSL reports it one level above the leaf (error 20 at depth 1). A private CA, or a client with an old or missing CA bundle, causes this.

    Input

    -----BEGIN CERTIFICATE-----
    MIIB7jCCAZWgAwIBAgIBBDAKBggqhkjOPQQDAjBBMRgwFgYDVQQKDA9mam9yZHRv
    b2xzIHRlc3QxJTAjBgNVBAMMHGZqb3JkdG9vbHMgdGVzdCBpbnRlcm1lZGlhdGUw
    HhcNMjYwMTAxMDAwMDAwWhcNMzYwMTAxMDAwMDAwWjAwMRgwFgYDVQQKDA9mam9y
    ZHRvb2xzIHRlc3QxFDASBgNVBAMMC3NlcnZlci50ZXN0MFkwEwYHKoZIzj0CAQYI
    KoZIzj0DAQcDQgAE7ee19O78yqmyOB5x/h4K7/QA6YW32XJesJT8lv2Q+Y0GBR4e
    r2DpKzlXcNQ5G7VN9GkztuzSnXch/wKr38FQdqOBjjCBizAMBgNVHRMBAf8EAjAA
    MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDATAWBgNVHREEDzAN
    ggtzZXJ2ZXIudGVzdDAdBgNVHQ4EFgQU/HjqRgLgUEQQDnr1y8nhCcb2baowHwYD
    VR0jBBgwFoAUMt7RDnv6EJHcKso7bd3VWZC9krowCgYIKoZIzj0EAwIDRwAwRAIg
    VatubrykL+ZDu2wIXIFzNCA4G6SIsUQnf2mw4c30KXMCICf1jBo0UciVihHiS1KE
    k6cc1SY9pCBuOPjwOoiC3ob3
    -----END CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    MIIBzzCCAXWgAwIBAgIBAzAKBggqhkjOPQQDAjA5MRgwFgYDVQQKDA9mam9yZHRv
    b2xzIHRlc3QxHTAbBgNVBAMMFGZqb3JkdG9vbHMgdGVzdCByb290MB4XDTI2MDEw
    MTAwMDAwMFoXDTM2MDEwMTAwMDAwMFowQTEYMBYGA1UECgwPZmpvcmR0b29scyB0
    ZXN0MSUwIwYDVQQDDBxmam9yZHRvb2xzIHRlc3QgaW50ZXJtZWRpYXRlMFkwEwYH
    KoZIzj0CAQYIKoZIzj0DAQcDQgAE8S+llYHyI61wNUPj0DPhpIyF+hRxM7dJFQdo
    lkEFplO8LVCXy7RgHxRttTDP+Od2kJV2tmdXrQXeLPMGOrG0C6NmMGQwEgYDVR0T
    AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDLe0Q57+hCR
    3CrKO23d1VmQvZK6MB8GA1UdIwQYMBaAFLcg9Ms28bssX2hEC2iuZ/lj9P4oMAoG
    CCqGSM49BAMCA0gAMEUCIQDEsN76EmigQQoI21DUJpyRdSt2nQdhomZ1IAkxNuLe
    4wIgL4BbGPQ84ODnLT1cTE2A2olMZgsjQDfiaRDDuW41iS8=
    -----END CERTIFICATE-----

    Certificate Decoder says

    leaf · issued by 2
    intermediate · issuer not in the input
  4. A proxy that inspects TLS

    A company proxy or a security product that opens TLS traffic signs every site with its own CA. A client that does not trust that CA fails on every site, not on one. Ask for the proxy's CA certificate and trust it.

How to fix it

  1. Make the server send the full chain: the leaf first, then each intermediate, the root left out. Let's Encrypt clients write that as fullchain.pem; nginx takes it in ssl_certificate.
  2. Paste what the server sends into the Certificate Decoder: the chain table shows every link and where one is missing. openssl s_client -showcerts lists what the server sends.
  3. If the client does not know the root, give it the CA certificate: curl --cacert ca.pem, NODE_EXTRA_CA_CERTS=ca.pem for Node, SSL_CERT_FILE=ca.pem for Python and OpenSSL.
  4. If every site fails, the client's CA bundle is missing or too old. Install or update it (the ca-certificates package on most Linux systems).
  5. Do not turn verification off (curl -k, NODE_TLS_REJECT_UNAUTHORIZED=0, verify=False). That removes the protection for every server, not just this one.

Related errors

More error explainers are coming

See all errors.