Skip to content
ecdsa.com
rustls (via reqwest, ureq, hyper-rustls, tonic)Rust

Error message

invalid peer certificate: UnknownIssuer

Also printed as

  • InvalidCertificate(UnknownIssuer)

reqwest prints it at the end of its source chain: "error sending request for url (…): client error (Connect): invalid peer certificate: UnknownIssuer"; Debug output shows InvalidCertificate(UnknownIssuer). ureq prints "io: invalid peer certificate: UnknownIssuer". Native binaries built on rustls (pnpm 12, many CLIs) show the same text.

rustls (via reqwest, ureq, hyper-rustls, tonic) — rustls::Error::InvalidCertificate(CertificateError::UnknownIssuer)

What it means

rustls could not chain the server's certificate to any trust anchor it was configured with. UnknownIssuer is rustls's single code for every path-building failure: a private or proxy CA, a missing intermediate, or a self-signed certificate. Which roots count as trusted depends on how the crate was built: the platform verifier (OS store), rustls-native-certs (OS roots loaded at start-up) or webpki-roots (Mozilla's list compiled in).

Why it happens

How to fix it

  1. 1.

    Add the root to the client

    ClientBuilder::add_root_certificate adds an anchor while keeping full verification (names, dates).

    rust
    // Trust a private root for this client (in addition to the default roots)
    let pem = std::fs::read("corp-root-ca.pem")?;
    let client = reqwest::Client::builder()
        .add_root_certificate(reqwest::Certificate::from_pem(&pem)?)
        .build()?;
  2. 2.

    Install the root in the OS store

    With the platform verifier (reqwest 0.13 default), roots in the operating system's store are trusted; on Linux, update-ca-certificates is enough.

    bash
    # reqwest 0.13 verifies with the platform verifier: install the root in the OS store
    sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt
    sudo update-ca-certificates
  3. 3.

    Check which root source is compiled in

    cargo tree shows whether webpki-roots or rustls-native-certs is used; switch features if the OS store must apply.

    bash
    # Which root source is compiled into this binary? (a crate that is absent reports no match)
    cargo tree -e features -i rustls-platform-verifier   # OS verifier (reqwest 0.13 default)
    cargo tree -e features -i rustls-native-certs        # OS roots loaded at start-up
    cargo tree -e features -i webpki-roots               # Mozilla roots compiled in, OS store ignored
  4. 4.

    Server owners: send the intermediate

    A single certificate in the handshake whose issuer is an intermediate means the server configuration is incomplete.

    bash
    openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'

Related errors

Browse the full signature error database