thanos-io/thanos · error

unable to load specified CA cert

Error message

unable to load specified CA cert %s: %s

What it means

The error produced by readCAFile when the configured CA bundle (tls_configs.ca_file) cannot be loaded — the file is unreadable, empty, or does not contain parseable PEM certificates. The path and underlying error are interpolated; the TLS config is rejected before use.

Solutions

  1. Verify the ca-file path exists and is readable by the process.
  2. Mount the secret/configmap correctly (Kubernetes).
  3. Fix the path; startup-time config errors are not retryable in place.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at pkg/exthttp/tlsconfig.go:65 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/279ccf65f59cc645. Report an issue: GitHub.

Appendix: source

Thrown at pkg/exthttp/tlsconfig.go:65

		return nil, fmt.Errorf("client cert file %q specified without client key file", cfg.CertFile)
	} else if len(cfg.KeyFile) > 0 && len(cfg.CertFile) == 0 {
		return nil, fmt.Errorf("client key file %q specified without client cert file", cfg.KeyFile)
	} else if len(cfg.CertFile) > 0 && len(cfg.KeyFile) > 0 {
		// Verify that client cert and key are valid.
		if _, err := cfg.getClientCertificate(nil); err != nil {
			return nil, err
		}
		tlsConfig.GetClientCertificate = cfg.getClientCertificate
	}

	return tlsConfig, nil
}

// readCAFile reads the CA cert file from disk.
func readCAFile(f string) ([]byte, error) {
	data, err := os.ReadFile(f)
	if err != nil {
		return nil, fmt.Errorf("unable to load specified CA cert %s: %s", f, err)
	}
	return data, nil
}

// updateRootCA parses the given byte slice as a series of PEM encoded certificates and updates tls.Config.RootCAs.
func updateRootCA(cfg *tls.Config, b []byte) bool {
	caCertPool := x509.NewCertPool()
	if !caCertPool.AppendCertsFromPEM(b) {
		return false
	}
	cfg.RootCAs = caCertPool
	return true
}

// getClientCertificate reads the pair of client cert and key from disk and returns a tls.Certificate.
func (c *TLSConfig) getClientCertificate(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
	cert, err := tls.LoadX509KeyPair(c.CertFile, c.KeyFile)
	if err != nil {

View on GitHub (pinned to 35b8b99117)