gastownhall/beads · error

ExternalDoltConfig: load client cert/key: %w

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.

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)

Solutions

  1. Confirm both files exist and are readable: ls -l <cert> <key>; fix permissions (chmod 600 on the key, correct owner).
  2. Verify cert and key match: compare `openssl x509 -noout -modulus` and `openssl rsa -noout -modulus` (or pub keys) — re-pair them if different.
  3. Ensure each file contains valid PEM blocks and TLSCert/TLSKey are not swapped.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/97b96bff0eed1d13. Report an issue: GitHub.