Skip to content

Errors

Every error the package produces, verbatim, with what causes it and what to change. All of them are github.com/cockroachdb/errors values, so errors.Is/errors.As reach the wrapped cause and %+v prints a stack trace.

They all surface while you are building a config. None of them can happen mid-flight on a live listener.

loading TLS certificate: …

loading TLS certificate: open /etc/certs/server.pem: no such file or directory

From Pair.Certificate, and so from ServerConfig and ApplyTo too. The wrapped cause comes straight from crypto/tls.LoadX509KeyPair, and covers more than a missing file:

Wrapped cause Meaning
open …: no such file or directory Wrong path, or a relative path resolved against a different working directory
open …: permission denied The process cannot read the file — check ownership and mode, which bites most often on the key
tls: failed to find any PEM data in certificate input cert is not PEM — DER, a PKCS#12 bundle, or an empty file
tls: failed to find any PEM data in key input Same, for key
tls: private key does not match public key cert and key are from different key pairs

unknown client_auth "…" (valid: "request", "verify-if-given", "require-verify")

unknown client_auth "require_verify" (valid: "request", "verify-if-given", "require-verify")

Pair.ClientAuth is set to something the package does not recognise. The comparison is exact: lower-case, hyphenated, no surrounding whitespace. Underscores, capitals and the crypto/tls constant names (RequireAndVerifyClientCert) are all rejected.

The rejection is deliberate. An unrecognised mode could only be handled by falling back to something, and every fallback is either a silent downgrade or a surprise — so it fails instead. See Why an unknown mode is an error rather than a fallback.

This error fires even when the config you are merging into already has its own client-certificate policy and the pair's would have been ignored.

client_auth "…" requires client_cas to verify against

client_auth "require-verify" requires client_cas to verify against

require-verify and verify-if-given both verify a client certificate against a CA pool, and no CA files were given. Set client_cas, or drop to request if you only want the certificate collected rather than checked.

request never produces this error — it does not verify anything.

reading CA file "…": …

reading CA file "/etc/certs/client-ca.pem": open /etc/certs/client-ca.pem: no such file or directory

From CertPool, and so from ClientConfig and from any pair with client_cas set. The file could not be read at all.

no certificates found in "…"

no certificates found in "/etc/certs/client-ca.pem"

The file was read but x509.CertPool.AppendCertsFromPEM found nothing usable in it. Usual causes: a DER file with a .pem name, a private key where a certificate was meant, a truncated download, or a file of PEM blocks that are not CERTIFICATE.

This is an error rather than a shrug on purpose: an empty trust store that verifies nothing looks exactly like a working one until something tries to connect.

nil TLS config

nil TLS config

Pair.ApplyTo(nil). Pass a config to merge into — &cryptotls.Config{} if you want an unhardened one, or tls.DefaultConfig() for the hardened base (at which point ServerConfig is the shorter spelling).

Handshake failures, which are not this package's errors

A rejected connection produces a crypto/tls error at the listener, not an error from this package. The common ones under mTLS:

Server log Cause
tls: client didn't provide a certificate require-verify and the client sent none
tls: failed to verify certificate: x509: certificate signed by unknown authority The client certificate does not chain to any CA in client_cas
tls: failed to verify certificate: x509: certificate specifies an incompatible key usage The client certificate carries an extended key usage that is not clientAuth — usually serverAuth copied from the server certificate. A certificate with no EKU at all is accepted
tls: client offered only unsupported versions: [301] The peer cannot do TLS 1.2
remote error: tls: bad certificate The peer rejected your certificate — usually missing CA trust on their side

tls: client didn't provide a certificate is also what you get from a Go client holding a certificate from the wrong CA. The server advertises which CAs it will accept, and a Go client silently withholds a certificate that does not match, so the mismatch reaches you as an absence rather than as a verification failure. A client that sends regardless — curl, or a Go client using GetClientCertificate — produces the unknown authority line instead. Both mean the same thing: the client certificate does not chain to anything in client_cas.

On the client side, x509: certificate signed by unknown authority from a Go client that used ClientConfig with CA files usually means the opposite of what it looks like: the server's certificate is fine and publicly trusted, but passing CA files replaced the system roots. See Private-CA trust replaces the system roots.