{"record":{"id":"d0c23354172cd8eb","repo":"microsoft/garnet","slug":"clienttargethost-should-be-provided-when-servercer","errorCode":null,"errorMessage":"ClientTargetHost should be provided when ServerCertificateRequired is enabled","messagePattern":"ClientTargetHost should be provided when ServerCertificateRequired is enabled","errorType":"exception","errorClass":"GarnetException","httpStatus":null,"severity":"error","filePath":"libs/server/TLS/GarnetTlsOptions.cs","lineNumber":175,"sourceCode":"\n            return new SslServerAuthenticationOptions\n            {\n                ClientCertificateRequired = ClientCertificateRequired,\n                CertificateRevocationCheckMode = CertificateRevocationCheckMode,\n                RemoteCertificateValidationCallback = ValidateClientCertificateCallback(IssuerCertificatePath),\n                ServerCertificateSelectionCallback = (sender, hostName) =>\n                {\n                    return serverCertificateSelector.GetSslServerCertificate();\n                }\n            };\n        }\n\n        SslClientAuthenticationOptions GetSslClientAuthenticationOptions()\n        {\n            if (ServerCertificateRequired && string.IsNullOrEmpty(ClientTargetHost))\n            {\n                logger?.LogError(\"ClientTargetHost should be provided when ServerCertificateRequired is enabled\");\n                throw new GarnetException(\"ClientTargetHost should be provided when ServerCertificateRequired is enabled\");\n            }\n            return new SslClientAuthenticationOptions\n            {\n                TargetHost = ClientTargetHost,\n                AllowRenegotiation = false,\n                CertificateRevocationCheckMode = CertificateRevocationCheckMode,\n                RemoteCertificateValidationCallback = ValidateServerCertificateCallback(ClientTargetHost, IssuerCertificatePath),\n                // We use the same server certificate selector for the server's own client as well\n                LocalCertificateSelectionCallback = (object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) =>\n                {\n                    return serverCertificateSelector.GetSslServerCertificate();\n                }\n            };\n        }\n\n        /// <summary>\n        /// Callback to verify the TLS certificate\n        /// </summary>","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/server/TLS/GarnetTlsOptions.cs#L157-L193","documentation":"Garnet's TLS client options require a ClientTargetHost (the SNI hostname) when ServerCertificateRequired is enabled. The target host is needed for TLS SNI extension and for remote certificate validation callbacks. Without it, the client cannot properly authenticate or validate the server. This check is in GetSslClientAuthenticationOptions(), which configures the server's own outbound TLS client (used for replication/clustering over TLS).","triggerScenarios":"Configuring TLS with ServerCertificateRequired=true but ClientTargetHost empty/null. This occurs when mutual TLS is enabled (the server acts as a TLS client to peers) but no target hostname is specified.","commonSituations":"Enabling mTLS for cluster replication without setting the peer hostname; config template that enables ServerCertificateRequired but leaves ClientTargetHost commented out; environment variable for the target host not set in production.","solutions":["Set --client-target-host <hostname> to the TLS SNI name of the peer server.","Disable --server-certificate-required if the server does not need to present a client certificate to peers.","Ensure the hostname matches the certificate's CN or SAN on the remote server."],"exampleFix":"// before\n--server-certificate-required\n\n// after\n--server-certificate-required --client-target-host garnet-peer.internal","handlingStrategy":"validation","validationCode":"if (options.ServerCertificateRequired && string.IsNullOrEmpty(options.ClientTargetHost))\n    throw new InvalidOperationException(\"--client-target-host is required when --server-certificate-required is enabled.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set --client-target-host when enabling mutual TLS (ServerCertificateRequired).","Ensure the target host matches the remote server's certificate CN or SAN.","Use a config validator for TLS settings in cluster/replication deployments."],"tags":["tls","certificate","configuration","client-auth","security","garnet"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}