router-for-me/CLIProxyAPI · error
home tls: client certificate and key must be set together
Error message
home tls: client certificate and key must be set together
What it means
Returned by the TLS-config builder in internal/home/client.go when exactly one of client-cert / client-key is set (after trimming). mTLS requires the pair together; supplying only one is treated as a configuration error rather than silently skipping client certificates.
Source
Thrown at internal/home/client.go:637
return nil, nil
}
serverName := strings.TrimSpace(cfg.ServerName)
if serverName == "" {
serverName = strings.TrimSpace(fallbackServerName)
}
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS12,
ServerName: serverName,
InsecureSkipVerify: cfg.InsecureSkipVerify,
}
clientCertPath := strings.TrimSpace(cfg.ClientCert)
clientKeyPath := strings.TrimSpace(cfg.ClientKey)
if clientCertPath != "" || clientKeyPath != "" {
if clientCertPath == "" || clientKeyPath == "" {
return nil, fmt.Errorf("home tls: client certificate and key must be set together")
}
certPair, errLoad := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
if errLoad != nil {
return nil, fmt.Errorf("home tls: load client certificate: %w", errLoad)
}
tlsConfig.Certificates = []tls.Certificate{certPair}
}
caCertPath := strings.TrimSpace(cfg.CACert)
if caCertPath == "" {
return tlsConfig, nil
}
caCertPEM, errRead := os.ReadFile(caCertPath)
if errRead != nil {
return nil, fmt.Errorf("home tls: read ca-cert: %w", errRead)
}
View on GitHub (pinned to 78f0c4079e)
Solutions
- Set both client-cert and client-key paths (or neither, if the server does not require mTLS)
- Check YAML indentation places both keys under the same home/tls block
- If using templating/secrets, assert both files exist before starting
Example fix
# before
home:
tls:
client-cert: /etc/cliproxy/client.pem
# after
home:
tls:
client-cert: /etc/cliproxy/client.pem
client-key: /etc/cliproxy/client.key Defensive patterns
Strategy: validation
Validate before calling
cert := strings.TrimSpace(cfg.TLS.ClientCert)
key := strings.TrimSpace(cfg.TLS.ClientKey)
if (cert == "") != (key == "") {
return errors.New("client-cert and client-key must both be set, or both omitted")
} Prevention
- Schema-validate configs (JSON schema or startup lint) rejecting half-set mTLS pairs
- In Kubernetes, use one secret containing both tls.crt/tls.key so they deploy atomically
When it happens
Trigger: Config sets client-cert but not client-key, or vice versa; one path left as an empty string while the other is populated; YAML indentation puts one key outside the home block.
Common situations: Copy-paste of a partial mTLS example; key path commented out accidentally; a templating variable for the key rendered empty in one environment (e.g. Kubernetes secret with a missing key).
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- home ca fingerprint is required
- home tls: load client certificate: %w
- home tls: read ca-cert: %w
- home ca fingerprint mismatch
- home ca certificate pem is invalid
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/e5f7c5759442ab84.
Report an issue: GitHub.