thanos-io/thanos · error
building client CA
Error message
building client CA
What it means
NewServerConfig wraps this error when the server's client-CA PEM file was read successfully but its certificates could not be parsed into an x509.CertPool via AppendCertsFromPEM, which returns false on any malformed/unparseable PEM data. It means the CA file exists but does not contain valid PEM-encoded certificates. The wrap also has a latent bug: it wraps the outer err (nil at that point) instead of a descriptive cause.
Solutions
- Verify the file contains valid PEM blocks: openssl x509 -in <cafile> -text -noout (or openssl storeutl) and fix/regenerate the file.
- Convert DER to PEM if needed: openssl x509 -inform DER -in ca.crt -out ca.pem.
- Ensure the mounted secret/ConfigMap actually contains the CA and was fully written (check file size, re-mount, restart pod).
- Re-export the full CA chain including intermediates into the bundle.
Example fix
// before
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caPEM) {
return nil, errors.Wrap(err, "building client CA")
}
// after
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caPEM) {
return nil, errors.New("building client CA: no valid PEM certificates in " + caCert)
} Defensive patterns
Strategy: validation
Validate before calling
func validatePEMCA(path string) error {
pem, err := os.ReadFile(path)
if err != nil { return err }
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(pem) {
return fmt.Errorf("%s contains no valid PEM certificates", path)
}
return nil
} Try / catch
cfg, err := tls.NewServerConfig(logger, ...)
if err != nil && strings.Contains(err.Error(), "building client CA") {
// CA file content is invalid PEM: check/fix the file before retrying
} Prevention
- Validate CA PEM files with `openssl x509 -text -noout` before deploying.
- Always distribute CAs as PEM, never DER.
- Verify mounted secret contents after rotation.
- Check file size > 0 at startup.
When it happens
Trigger: NewServerConfig(..., clientCAPath, ...) is called with a caCert file whose contents are not valid PEM certificate blocks (e.g. empty file, DER-encoded cert, private key, concatenated garbage, or a truncated download).
Common situations: Pointing --client-ca-file at a DER .crt instead of PEM; a secret/ConfigMap mounted empty or truncated; a file containing only a private key or CSR; copy-paste corruption of a CA bundle; a renewal process writing partial content mid-read.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- parsing downstream tripper TLS config YAML
- setup gRPC server
- Improper http client config
- could not get organization field from client cert
- could not get organizationalUnit field from client cert
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/49630ba0944659a9.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/tls/options.go:85
}
mngr := &serverTLSManager{
srvCertPath: certPath,
srvKeyPath: keyPath,
srvCert: &certificate,
}
tlsCfg.GetCertificate = mngr.getCertificate
if clientCA != "" {
caPEM, err := os.ReadFile(filepath.Clean(clientCA))
if err != nil {
return nil, errors.Wrap(err, "reading client CA")
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caPEM) {
return nil, errors.Wrap(err, "building client CA")
}
tlsCfg.ClientCAs = certPool
tlsCfg.ClientAuth = tls.RequireAndVerifyClientCert
level.Info(logger).Log("msg", "server TLS client verification enabled")
}
return tlsCfg, nil
}
type serverTLSManager struct {
srvCertPath string
srvKeyPath string
mtx sync.Mutex
srvCert *tls.Certificate
srvCertModTime time.Time
srvKeyModTime time.TimeView on GitHub (pinned to 35b8b99117)