thanos-io/thanos · error

server credentials

Error message

server credentials

What it means

NewServerConfig wraps a failure from tls.LoadX509KeyPair with the message 'server credentials'. This means the server certificate/key files could not be loaded — unreadable files, invalid PEM data, or a cert/key mismatch.

Solutions

  1. Verify both paths exist and are readable by the process: 'openssl x509 -in server.crt -noout' and 'openssl rsa -in server.key -check'
  2. Confirm cert and key match: compare 'openssl x509 -noout -modulus' and 'openssl rsa -noout -modulus' output
  3. Re-export the Kubernetes secret / re-copy the files if contents are corrupt
  4. Check file permissions and mount paths match what the flags point to

Example fix

// before (mismatched pair)
--cert=server-new.crt --key=server-old.key
// after
--cert=server-new.crt --key=server-new.key
Defensive patterns

Strategy: validation

Validate before calling

// Validate pair before starting the server
if _, err := tls.LoadX509KeyPair(certPath, keyPath); err != nil {
    return fmt.Errorf("invalid server keypair: %w", err)
}

Prevention

When it happens

Trigger: tls.LoadX509KeyPair(certPath, keyPath) fails during NewServerConfig because a file is missing/unreadable, PEM blocks are invalid, or the private key does not match the certificate.

Common situations: Wrong file paths or missing secret mounts; concatenated or garbled PEM files; key/cert pair from different issuers after rotation; files without read permission for the process user.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at pkg/tls/options.go:66

		MinVersion: minTlsVersion,
	}

	cipherSuiteIDs, err := getCipherSuiteIDs(ciphers)
	if err != nil {
		return nil, err
	}
	tlsCfg.CipherSuites = cipherSuiteIDs

	curveIDs, err := getCurveIDs(curves)
	if err != nil {
		return nil, err
	}
	tlsCfg.CurvePreferences = curveIDs

	// Certificate is loaded during server startup to check for any errors.
	certificate, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		return nil, errors.Wrap(err, "server credentials")
	}

	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) {

View on GitHub (pinned to 35b8b99117)