temporalio/temporal · error
failed to append CA file
Error message
failed to append CA file
What it means
After the CA file is read successfully, registerTLSConfig parses it with x509.AppendCertsFromPEM; if no certificates could be parsed from the bytes, it returns "failed to append CA file". This means the file exists but does not contain any valid PEM-encoded certificates.
Source
Thrown at common/persistence/sql/sqlplugin/mysql/session/session.go:219
}
}
func registerTLSConfig(cfg *config.SQL) error {
if cfg.TLS == nil || !cfg.TLS.Enabled {
return nil
}
// TODO: create a way to set MinVersion and CipherSuites via cfg.
tlsConfig := auth.NewTLSConfigForServer(cfg.TLS.ServerName, cfg.TLS.EnableHostVerification)
if cfg.TLS.CaFile != "" {
rootCertPool := x509.NewCertPool()
pem, err := os.ReadFile(cfg.TLS.CaFile)
if err != nil {
return fmt.Errorf("failed to load CA files: %v", err)
}
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
return fmt.Errorf("failed to append CA file")
}
tlsConfig.RootCAs = rootCertPool
}
if cfg.TLS.CertFile != "" && cfg.TLS.KeyFile != "" {
clientCert := make([]tls.Certificate, 0, 1)
certs, err := tls.LoadX509KeyPair(
cfg.TLS.CertFile,
cfg.TLS.KeyFile,
)
if err != nil {
return fmt.Errorf("failed to load tls x509 key pair: %v", err)
}
clientCert = append(clientCert, certs)
tlsConfig.Certificates = clientCert
}
// In order to use the TLS configuration you need to register it. Once registered you use it by specifyingView on GitHub (pinned to bde624efd1)
Solutions
- Verify the file contains PEM blocks (-----BEGIN CERTIFICATE-----) with: openssl x509 -in ca.pem -text -noout.
- Convert DER certificates to PEM: openssl x509 -inform der -in ca.crt -out ca.pem.
- Re-create/re-mount the secret and confirm the file is non-empty and uncorrupted inside the container.
- Concatenate the full CA chain (intermediates + root) into the file if the server uses an intermediate chain.
Example fix
// before: ca.pem contains a DER binary certificate // convert it openssl x509 -inform der -in ca.crt -out /etc/temporal/certs/ca.pem // after: ca.pem starts with // -----BEGIN CERTIFICATE-----
Defensive patterns
Strategy: validation
Validate before calling
pemBytes, err := os.ReadFile(cfg.TLS.CaFile)
if err != nil { return err }
if !x509.NewCertPool().AppendCertsFromPEM(pemBytes) {
return fmt.Errorf("file %q contains no valid PEM certificates", cfg.TLS.CaFile)
} Type guard
func isValidPEMCA(path string) bool {
b, err := os.ReadFile(path)
if err != nil { return false }
return x509.NewCertPool().AppendCertsFromPEM(b)
} Try / catch
if err := connectDB(cfg); err != nil {
if strings.Contains(err.Error(), "failed to append CA file") {
// convert cert to PEM (openssl x509 -inform der ...) and retest
}
return err
} Prevention
- Always supply PEM (not DER) certificates; verify with openssl x509 -in ca.pem -text -noout.
- Confirm mounted secrets are non-empty inside the container before starting services.
- Include the full CA chain (intermediates plus root) in the CA file.
When it happens
Trigger: createConnection -> registerTLSConfig where TLS.CaFile points to an existing file whose contents are not parseable PEM certificates (empty file, wrong format, DER-encoded cert, concatenated junk).
Common situations: Secret mounted as an empty/placeholder file; DER (.crt binary) cert provided instead of PEM; file containing a private key or chain without the CA cert; truncation during secret provisioning; YAML inlining mangling the PEM.
Related errors
- failed to load CA files: %v
- failed to load tls x509 key pair: %v
- failed to register tls config: %v
- only one of keyData or keyFile properties should be specifie
- only one of caData or caFile properties should be specified
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/22d45dd97138c0a5.
Report an issue: GitHub.