t8y2/dbx · error

Hive client certificate and key must be configured together

Error message

Hive client certificate and key must be configured together

What it means

Mutual TLS for the Hive connection requires both the client certificate and its private key. If exactly one of clientCertPath / clientKeyPath is set, the library aborts with this error because tls.LoadX509KeyPair needs both files and a half-configured mTLS setup is always a mistake.

Source

Thrown at agents/drivers/argo-go/config.go:1085

		certificates, err := loadTrustStore(
			trustStoreLocation,
			parameter(values, "truststorepassword"),
			parameter(values, "truststoretype"),
		)
		if err != nil {
			return nil, fmt.Errorf("load Hive truststore: %w", err)
		}
		if customRoots == nil {
			customRoots = x509.NewCertPool()
		}
		for _, certificate := range certificates {
			customRoots.AddCert(certificate)
		}
	}
	config.RootCAs = customRoots
	if params.ClientCertPath != "" || params.ClientKeyPath != "" {
		if params.ClientCertPath == "" || params.ClientKeyPath == "" {
			return nil, errors.New("Hive client certificate and key must be configured together")
		}
		certificate, err := tls.LoadX509KeyPair(params.ClientCertPath, params.ClientKeyPath)
		if err != nil {
			return nil, fmt.Errorf("load Hive client certificate: %w", err)
		}
		config.Certificates = []tls.Certificate{certificate}
	}
	keyStoreLocation := parameter(values, "sslkeystore")
	if keyStoreLocation != "" {
		if parameter(values, "keystorepassword") == "" && credentialProviderPath != "" {
			return nil, errors.New("Hive storePasswordPath uses the Java Hadoop credential-provider format; configure keyStorePassword explicitly for the native agent")
		}
		certificate, err := loadClientKeyStore(
			keyStoreLocation,
			parameter(values, "keystorepassword"),
			parameter(values, "keystoretype"),
		)
		if err != nil {

View on GitHub (pinned to c0390bff16)

Solutions

  1. Set both parameters: clientCertPath to the certificate PEM and clientKeyPath to the matching private key PEM.
  2. If your PEM file combines cert and key, either split it into two files (openssl pkey / openssl x509 extraction) and set both paths, or point both parameters at the same combined file if the loader accepts it.
  3. Check the secret/volume mount so that both files actually exist at runtime (kubectl exec ... ls -l) before the agent starts.
  4. If mTLS is not required (server-only TLS), unset both clientCertPath and clientKeyPath entirely instead of leaving one set.

Example fix

// before
params.ClientCertPath = "/etc/hive/tls/client.crt"
// ClientKeyPath left empty
// after
params.ClientCertPath = "/etc/hive/tls/client.crt"
params.ClientKeyPath = "/etc/hive/tls/client.key"
Defensive patterns

Strategy: validation

Validate before calling

func validateClientTLS(p ConfigParams) error {
	if (p.ClientCertPath == "") != (p.ClientKeyPath == "") {
		return errors.New("client certificate and key must both be set or both unset")
	}
	if p.ClientCertPath != "" {
		if _, err := tls.LoadX509KeyPair(p.ClientCertPath, p.ClientKeyPath); err != nil {
			return err
		}
	}
	return nil
}

Type guard

func mtlsComplete(p ConfigParams) bool {
	return (p.ClientCertPath == "" && p.ClientKeyPath == "") ||
		(p.ClientCertPath != "" && p.ClientKeyPath != "")
}

Try / catch

cfg, err := buildConfig(params)
if err != nil {
	if strings.Contains(err.Error(), "configured together") {
		return fmt.Errorf("mtls config incomplete: set both clientCertPath and clientKeyPath: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling the Hive TLS config path with only one of params.ClientCertPath or params.ClientKeyPath set (the other empty string).

Common situations: DSN/config copied from an example where the key was provided separately by the environment; a secret mount failed so only cert.pem was present; the key file path was omitted because the PEM cert file contains both cert and key (combined PEM is not handled here — both parameters must be set).

Understand the failure class

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/8d3a643d8bb3ef73. Report an issue: GitHub.