Error message
remote error: tls: unknown certificate authority
Go servers log "http: TLS handshake error from <client>: remote error: tls: unknown certificate authority". In our tests, OpenSSL 3.5 clients rejecting the same certificate over TLS 1.3 were logged by the Go 1.27 server as "local error: tls: bad record MAC" instead, and Go clients send bad_certificate (logged as "remote error: tls: bad certificate").
Go crypto/tls — TLS alert 48 (unknown_ca) received from the peer, e.g. an OpenSSL-based client rejecting a Go server's certificate
What it means
The peer sent TLS alert 48 (unknown_ca): it could not chain the certificate it received to a CA it trusts. In a Go server's log it means a client (OpenSSL-based: curl, Python, Ruby, PHP, nginx as a proxy) rejected the server's certificate during a TLS 1.2 handshake. In a Go client it means the server rejected the client certificate in mutual TLS.
Why it happens
The client does not trust the issuing CA
commonPrivate or company CAs that the client machines or containers do not have.
The Go server sends only its leaf
commonListenAndServeTLS sends exactly the certificates in the file; a file with only the leaf leaves clients unable to reach a root.
Mutual TLS: the server does not trust the client's CA
occasionalOn the client side, this alert means the server's ClientCAs do not include the client certificate's issuer.
How to fix it
- 1.
Check the served chain from a client
If only the leaf is sent, fix the file; if the chain ends at a private root, install that root on the clients.
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:|Verify return code' - 2.
Serve the full chain from Go
Put the leaf and its intermediates into the PEM file passed to ListenAndServeTLS (or tls.LoadX509KeyPair).
go // Leaf + intermediates in one file; Go sends every certificate in it srv := &http.Server{Addr: ":443"} log.Fatal(srv.ListenAndServeTLS("fullchain.pem", "server.key")) - 3.
Install the private root on clients
For internal services, distribute the company root to the systems and containers that call the server.
bash # Private CA: install the root on the clients (Debian/Ubuntu example) sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt && sudo update-ca-certificates