thanos-io/thanos · error
both client key and certificate must be provided
Error message
both client key and certificate must be provided
What it means
NewClientConfig returns this error when exactly one of cert and key is non-empty. Mutual TLS requires the client certificate and its private key to be supplied together; a lone half is a configuration error.
Solutions
- Provide both cert and key paths together, or neither.
- Check the corresponding flags/env vars are both set (e.g. TLS_CERT and TLS_KEY).
- Mount both files from the secret and pass both paths.
- If mTLS is not required, omit both to use an unauthenticated client.
Example fix
// before
cfg, err := tls.NewClientConfig(logger, certPath, "", caPath, serverName, false, "1.2")
// after
if (certPath == "") != (keyPath == "") {
return errors.New("client cert and key must both be set")
}
cfg, err := tls.NewClientConfig(logger, certPath, keyPath, caPath, serverName, false, "1.2") Defensive patterns
Strategy: validation
Validate before calling
func havePair(cert, key string) error {
if (cert == "") != (key == "") {
return errors.New("client cert and key must be provided together")
}
return nil
} Try / catch
if err := havePair(certPath, keyPath); err != nil {
return err
}
cfg, err := tls.NewClientConfig(logger, certPath, keyPath, caCert, serverName, skipVerify, ver) Prevention
- Group cert+key under one config section/secret so they travel together.
- Validate both fields in config loading before calling the library.
- Use a single env var prefix (TLS_CERT_*/TLS_KEY_*) and check both.
- Fail at startup, not on first connection.
When it happens
Trigger: StoreClientTLSCredentials calls NewClientConfig with cert set but key empty (or vice versa) when configuring mTLS.
Common situations: Only the cert file was mounted/secret-shared, the key was omitted for security; one of the two env vars/flags misnamed; TLS config template filled partially; copy-paste dropped the key path line.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- invalid cipher suite
- invalid curve: , valid values are
- invalid TLS version: , valid values are
- unsupported format for label
- --auto-gomemlimit.ratio must be greater than 0 and less…
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/3db25792a347176a.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/tls/options.go:181
return nil, err
}
level.Debug(logger).Log("msg", fmt.Sprintf("setting minimum TLS version to %s", minTLSVersion))
}
tlsCfg := &tls.Config{
RootCAs: certPool,
MinVersion: mtlsVersion,
}
if serverName != "" {
tlsCfg.ServerName = serverName
}
if skipVerify {
tlsCfg.InsecureSkipVerify = true
}
if (key != "") != (cert != "") {
return nil, errors.New("both client key and certificate must be provided")
}
if cert != "" {
mngr := &clientTLSManager{
certPath: cert,
keyPath: key,
}
tlsCfg.GetClientCertificate = mngr.getClientCertificate
level.Debug(logger).Log("msg", "TLS client authentication enabled")
}
return tlsCfg, nil
}
type clientTLSManager struct {
certPath string
keyPath string
View on GitHub (pinned to 35b8b99117)