gastownhall/beads · error
ExternalDoltConfig: load client cert/key
Error message
ExternalDoltConfig: load client cert/key: %w
What it means
TLSClientConfig failed to load the client certificate/key pair via tls.LoadX509KeyPair and wraps the underlying error. Common wrapped causes: file not found, permission denied, malformed PEM, or the cert and key not matching (different public keys). This is required when mutual TLS is configured with TLSCert set.
Solutions
- Confirm both files exist and are readable: ls -l <cert> <key>; fix permissions (chmod 600 on the key, correct owner).
- Verify cert and key match: compare `openssl x509 -noout -modulus` and `openssl rsa -noout -modulus` (or pub keys) — re-pair them if different.
- Ensure each file contains valid PEM blocks and TLSCert/TLSKey are not swapped.
- Remove TLSCert/TLSKey if mutual TLS is not actually required by the server.
Example fix
// before tlsCert: "/etc/beads/tls/client-new.pem" // renewed cert tlsKey: "/etc/beads/tls/client-old.key" // stale key -> mismatch // after tlsCert: "/etc/beads/tls/client-new.pem" tlsKey: "/etc/beads/tls/client-new.key"
Defensive patterns
Strategy: try-catch
Validate before calling
if cfg.TLSCert != "" && cfg.TLSKey != "" {
if _, err := tls.LoadX509KeyPair(cfg.TLSCert, cfg.TLSKey); err != nil {
return fmt.Errorf("client keypair precheck failed: %w", err)
}
} Try / catch
cfg, err := extCfg.TLSClientConfig()
if err != nil && strings.Contains(err.Error(), "load client cert/key") {
log.Fatalf("mTLS keypair bad (missing/unreadable/mismatched?): %v\nverify with: openssl x509 -noout -modulus <cert> && openssl rsa -noout -modulus <key>", err)
} Prevention
- Renew cert and key together, atomically
- chmod 600 private keys and ensure the service user owns them
- Verify cert/key match after any rotation before restarting services
When it happens
Trigger: Calling registerExternalTLSConfig -> TLSClientConfig with TLSCert/TLSKey paths pointing to missing files, unreadable keys, non-PEM content, or mismatched cert/key files.
Common situations: Key deployed without read permission for the service user; cert renewed but key not (or vice versa) causing mismatch; cert copied without its key; files swapped (key in TLSCert field); encrypted key with passphrase not supported by LoadX509KeyPair.
Related errors
- ExternalDoltConfig: read TLSCACert
- ExternalDoltConfig: TLSCACert
- atomicfile: close
- atomicfile: create temp
- cannot access file
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/97b96bff0eed1d13.
Report an issue: GitHub.
Appendix: source
Thrown at internal/configfile/external_dolt_config.go:136
cfg.ServerName = name
}
if c.TLSCACert != "" {
pem, err := os.ReadFile(c.TLSCACert)
if err != nil {
return nil, fmt.Errorf("ExternalDoltConfig: read TLSCACert: %w", err)
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("ExternalDoltConfig: TLSCACert %q: no certificates parsed", c.TLSCACert)
}
cfg.RootCAs = pool
}
if c.TLSCert != "" {
crt, err := tls.LoadX509KeyPair(c.TLSCert, c.TLSKey)
if err != nil {
return nil, fmt.Errorf("ExternalDoltConfig: load client cert/key: %w", err)
}
cfg.Certificates = []tls.Certificate{crt}
}
return cfg, nil
}
View on GitHub (pinned to 71377f2769)