{"record":{"id":"37e41eb55bbf2ca0","repo":"temporalio/temporal","slug":"failed-to-load-client-ca-v","errorCode":null,"errorMessage":"failed to load client ca: %v","messagePattern":"failed to load client ca: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/rpc/encryption/local_store_tls_provider.go","lineNumber":376,"sourceCode":"\t}\n\treturn auth.NewTLSConfigWithCertsAndCAs(\n\t\tclientAuthType,\n\t\t[]tls.Certificate{*serverCert},\n\t\tclientCaPool,\n\t\tlogger), nil\n}\n\nfunc newClientTLSConfig(\n\tclientProvider CertProvider,\n\tserverName string,\n\tisAuthRequired bool,\n\tisWorker bool,\n\tenableHostVerification bool,\n) (*tls.Config, error) {\n\t// Optional ServerCA for client if not already trusted by host\n\tserverCa, err := clientProvider.FetchServerRootCAsForClient(isWorker)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to load client ca: %v\", err)\n\t}\n\n\tvar getCert tlsCertFetcher\n\n\t// mTLS enabled, present certificate\n\tif isAuthRequired {\n\t\tgetCert = func() (*tls.Certificate, error) {\n\t\t\tcert, err := clientProvider.FetchClientCertificate(isWorker)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tif cert == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"client auth required, but no certificate provided\")\n\t\t\t}\n\t\t\treturn cert, nil\n\t\t}\n\t}","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/rpc/encryption/local_store_tls_provider.go#L358-L394","documentation":"newClientTLSConfig fetches the optional server root CA used by the client (clientProvider.FetchServerRootCAsForClient(isWorker)) for connections to servers whose certs are not in the system trust store. A failure is wrapped as \"failed to load client ca: %v\". Raised for internode and frontend client TLS config construction.","triggerScenarios":"Building a client TLS config (GetInternodeClientConfig / GetFrontendClientConfig / anonymous worker config) where the configured server CA file/data for clients is missing, unreadable, or unparseable.","commonSituations":"Worker or CLI configured with server CA path that does not exist in its container; self-signed server certs with a stale/mistyped CA path; permission issues after secret mount; typo between serverName and CA file layout.","solutions":["Fix the wrapped root cause: ensure the client's server CA file exists, is readable, and is valid PEM.","If the server cert is already trusted by the host's system roots, remove the redundant server CA config.","Re-copy the CA bundle after rotation; verify with openssl x509 -in ca.pem -noout -text.","Check worker-vs-non-worker config split: internode and frontend worker settings each have their own CA paths."],"exampleFix":"// before\nclientTLS:\n  internode:\n    serverName: tls-server\n    rootCADataFile: /etc/certs/ca.pem   # not mounted in worker pod\n// after\nclientTLS:\n  internode:\n    serverName: tls-server\n    rootCADataFile: /etc/temporal/tls/internode-ca.pem   # mounted secret","handlingStrategy":"validation","validationCode":"if rootCAPath != \"\" {\n    b, err := os.ReadFile(rootCAPath)\n    if err != nil { return fmt.Errorf(\"client root CA unreadable: %w\", err) }\n    if _, err := x509.SystemCertPool(); err == nil {\n        pool := x509.NewCertPool()\n        if !pool.AppendCertsFromPEM(b) { return errors.New(\"root CA PEM not parseable\") }\n    }\n}","typeGuard":null,"tryCatchPattern":"tlsCfg, err := newClientTLSConfig(...)\nif err != nil && strings.Contains(err.Error(), \"failed to load client ca\") {\n    return fmt.Errorf(\"cannot connect over TLS: %w\", err)\n}","preventionTips":["Mount the server CA bundle in every client/worker pod that needs it.","Re-copy the CA after server cert rotation.","Drop explicit CA config when the server uses publicly trusted certs."],"tags":["tls","client","ca","root-ca"],"backgroundTag":"tls-root-ca-load-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}