{"record":{"id":"66d729f1717f7dcd","repo":"temporalio/temporal","slug":"failed-to-fetch-client-cas-v","errorCode":null,"errorMessage":"failed to fetch client CAs: %v","messagePattern":"failed to fetch client CAs: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"common/rpc/encryption/local_store_tls_provider.go","lineNumber":351,"sourceCode":"\t\treturn nil, fmt.Errorf(\"loading server tls certificate failed: %v\", err)\n\t}\n\n\t// tls disabled, responsibility of cert provider above to error otherwise\n\tif serverCert == nil {\n\t\treturn nil, nil\n\t}\n\n\t// Default to NoClientAuth\n\tclientAuthType := tls.NoClientCert\n\tvar clientCaPool *x509.CertPool\n\n\t// If mTLS enabled\n\tif requireClientAuth {\n\t\tclientAuthType = tls.RequireAndVerifyClientCert\n\n\t\tca, err := certProvider.FetchClientCAs()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to fetch client CAs: %v\", err)\n\t\t}\n\n\t\tclientCaPool = ca\n\t}\n\tif remoteAddress != \"\" { // remoteAddress==\"\" when we return initial tls.Config object when configuring server\n\t\tlogger.Debug(\"returning TLS config for connection\", tag.Address(remoteAddress), tag.ServerName(serverName))\n\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,","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/rpc/encryption/local_store_tls_provider.go#L333-L369","documentation":"When mutual TLS is enabled (requireClientAuth), the server fetches the CA pool used to verify client certificates via certProvider.FetchClientCAs(). Any failure is wrapped as \"failed to fetch client CAs: %v\". This blocks construction of the server TLS config, since client certificate verification requires a trust pool.","triggerScenarios":"Server TLS config built with requireClientAuth=true and the provider's client-CA file/data is missing, unreadable, or contains no parseable certificates (propagating errors like 390 from parseCert/buildCAPool).","commonSituations":"mTLS enabled but ClientCA (clientCADataFile / clientCAData) not configured or pointing to a wrong path; CA bundle file empty after secret rotation; clients authenticate with certs issued by a CA whose bundle failed to load.","solutions":["Check the wrapped error for the root cause (path, permissions, PEM decode) and fix the client CA source.","Ensure clientCADataFile (or inline clientCAData) contains a valid PEM CA bundle.","Confirm the CA bundle includes the CA that actually signed your client certificates.","If mTLS is not needed, set requireClientAuth=false so the CA fetch is skipped."],"exampleFix":"// before\nserverTLS:\n  requireClientAuth: true   # clientCADataFile missing\n// after\nserverTLS:\n  requireClientAuth: true\n  clientCADataFile: /etc/temporal/tls/client-ca.pem","handlingStrategy":"validation","validationCode":"caPEM, err := os.ReadFile(cfg.ClientCADataFile)\nif err != nil { return fmt.Errorf(\"client CA unreadable: %w\", err) }\nif !hasPEMCert(caPEM) { return errors.New(\"client CA bundle has no certificates\") }","typeGuard":null,"tryCatchPattern":"cfg, err := getServerTLSConfigFromCertProvider(...)\nif err != nil && strings.Contains(err.Error(), \"failed to fetch client CAs\") {\n    // disable mTLS only if policy allows; otherwise fail fast\n    logger.Fatal(\"client CA pool unavailable for mTLS\", \"cause\", err)\n}","preventionTips":["Ship the client CA bundle in the same secret/volume lifecycle as the server cert.","Confirm the bundle signs all client certs you intend to accept.","Run a pre-start config validation that decodes the CA pool."],"tags":["tls","mtls","ca","server"],"backgroundTag":"mtls-client-ca-load-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}