{"record":{"id":"edbc018c97d2d444","repo":"temporalio/temporal","slug":"failed-to-load-ca-files-v","errorCode":null,"errorMessage":"failed to load CA files: %v","messagePattern":"failed to load CA files: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/persistence/sql/sqlplugin/mysql/session/session.go","lineNumber":216,"sourceCode":"\t\treturn key, value\n\tdefault:\n\t\treturn inkey, invalue\n\t}\n}\n\nfunc registerTLSConfig(cfg *config.SQL) error {\n\tif cfg.TLS == nil || !cfg.TLS.Enabled {\n\t\treturn nil\n\t}\n\n\t// TODO: create a way to set MinVersion and CipherSuites via cfg.\n\ttlsConfig := auth.NewTLSConfigForServer(cfg.TLS.ServerName, cfg.TLS.EnableHostVerification)\n\n\tif cfg.TLS.CaFile != \"\" {\n\t\trootCertPool := x509.NewCertPool()\n\t\tpem, err := os.ReadFile(cfg.TLS.CaFile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load CA files: %v\", err)\n\t\t}\n\t\tif ok := rootCertPool.AppendCertsFromPEM(pem); !ok {\n\t\t\treturn fmt.Errorf(\"failed to append CA file\")\n\t\t}\n\t\ttlsConfig.RootCAs = rootCertPool\n\t}\n\n\tif cfg.TLS.CertFile != \"\" && cfg.TLS.KeyFile != \"\" {\n\t\tclientCert := make([]tls.Certificate, 0, 1)\n\t\tcerts, err := tls.LoadX509KeyPair(\n\t\t\tcfg.TLS.CertFile,\n\t\t\tcfg.TLS.KeyFile,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load tls x509 key pair: %v\", err)\n\t\t}\n\t\tclientCert = append(clientCert, certs)\n\t\ttlsConfig.Certificates = clientCert","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/sql/sqlplugin/mysql/session/session.go#L198-L234","documentation":"registerTLSConfig in the MySQL session package reads the configured CA PEM file (cfg.TLS.CaFile) to build the root certificate pool for the connection; if os.ReadFile fails, the error is wrapped as \"failed to load CA files\". The MySQL client cannot establish verified TLS without this file.","triggerScenarios":"createConnection -> registerTLSConfig with a non-empty TLS.CaFile that points to a nonexistent, unreadable, or otherwise un-openable file path.","commonSituations":"Typo in the CA file path in config; file not mounted into a container (missing volume mount); permission denied for the service user; relative path used with a different working directory in a container.","solutions":["Verify the path in TLS.CaFile exists and is readable by the Temporal process user (ls -l / check permissions).","Use an absolute path in containerized deployments and ensure the file is mounted (e.g., via a Kubernetes secret volume).","Fix ownership/permissions (chmod/chown) so the service account can read the PEM file.","If TLS verification is not required for the environment, remove the CaFile setting — but prefer fixing the mount for security."],"exampleFix":"// before (config)\ntls:\n  caFile: certs/ca.pem\n// after\ntls:\n  caFile: /etc/temporal/certs/ca.pem  # absolute path, verified mounted & readable","handlingStrategy":"validation","validationCode":"caPath := cfg.TLS.CaFile\nif fi, err := os.Stat(caPath); err != nil || fi.Size() == 0 {\n    return fmt.Errorf(\"CA file %q missing or empty\", caPath)\n}\nif f, err := os.Open(caPath); err != nil {\n    return fmt.Errorf(\"CA file %q not readable: %v\", caPath, err)\n} else { f.Close() }","typeGuard":null,"tryCatchPattern":"if err := connectDB(cfg); err != nil {\n    if strings.Contains(err.Error(), \"failed to load CA files\") {\n        // fix caFile path/mount/permissions before reconnect\n    }\n    return err\n}","preventionTips":["Use absolute paths for TLS files in containers.","Mount CA files as read-only volumes (K8s secrets) and verify at pod startup.","Add a startup check that stats and reads every configured TLS file."],"tags":["tls","mysql","configuration","file-io"],"backgroundTag":"ca-file-not-found","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}