gastownhall/beads · error
ExternalDoltConfig: TLSCACert %q: no certificates parsed
Error message
ExternalDoltConfig: TLSCACert %q: no certificates parsed
What it means
TLSClientConfig read the TLSCACert file successfully but x509.AppendCertsFromPEM could not parse any certificates from its contents. The file exists but is not a valid PEM-encoded certificate bundle (or is empty/wrong type). The root CA pool would be empty, so the config is rejected.
Source
Thrown at internal/configfile/external_dolt_config.go:128
if c.TLSSkipVerify {
cfg.InsecureSkipVerify = true //nolint:gosec // G402: opt-in insecure transport via the TLSSkipVerify testing flag
} else {
name := c.TLSServerName
if name == "" {
name = c.Host
}
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
- Verify the file starts with '-----BEGIN CERTIFICATE-----' (head -1 file); re-export in PEM format if not (openssl x509 -inform DER -in ca.der -out ca.pem).
- Check the file is non-empty and not truncated (openssl x509 -in ca.pem -noout -subject).
- Make sure TLSCACert points to the CA certificate, not a private key or leaf key.
- Re-download/copy the CA bundle from the server operator.
Example fix
// before tlsCACert: "/etc/beads/tls/ca.der" // DER encoded // after # openssl x509 -inform DER -in ca.der -out /etc/beads/tls/ca.pem tlsCACert: "/etc/beads/tls/ca.pem"
Defensive patterns
Strategy: validation
Validate before calling
pem, err := os.ReadFile(cfg.TLSCACert)
if err != nil {
return err
}
if !x509.NewCertPool().AppendCertsFromPEM(pem) {
return fmt.Errorf("%s contains no PEM certificates", cfg.TLSCACert)
} Type guard
func isPEMCert(path string) bool {
b, err := os.ReadFile(path)
if err != nil || len(b) == 0 {
return false
}
return x509.NewCertPool().AppendCertsFromPEM(b)
} Try / catch
cfg, err := extCfg.TLSClientConfig()
if err != nil && strings.Contains(err.Error(), "no certificates parsed") {
return fmt.Errorf("CA file at %s is not PEM; re-export with: openssl x509 -inform DER -in ca.der -out ca.pem", extCfg.TLSCACert)
} Prevention
- Always export CAs in PEM format (openssl x509, not DER)
- Sanity-check downloaded certs with openssl x509 -noout -subject before use
- Never point TLSCACert at key files or HTML pages
When it happens
Trigger: Calling registerExternalTLSConfig -> TLSClientConfig where TLSCACert contains DER-encoded bytes, a private key, an empty file, HTML (e.g. an error page saved as ca.pem), or concatenated garbage.
Common situations: Downloading a CA cert that saved as DER instead of PEM; accidentally pointing TLSCACert at the server cert's key file; truncated file from a failed transfer; empty placeholder file created by config tooling.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- ExternalDoltConfig: read TLSCACert: %w
- ExternalDoltConfig: load client cert/key: %w
- ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired
- ExternalDoltConfig: TLSServerName set without TLSRequired
- ExternalDoltConfig: TLSSkipVerify set without TLSRequired
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3945fd7abc81f27f.
Report an issue: GitHub.