Cannot connect to gRPC server using TLS
09:04 11 Feb 2026

I'm trying to connect to a gRPC server using TLS (gRPC version 1.76.0) on Windows. However, I'm getting the following errors in the console:

WARNING: All log messages before absl::InitializeLog() is called are written to STDERR

E0000 00:00:1770816303.480934 5684 ssl_transport_security.cc:886] Could not load any root certificate.

E0000 00:00:1770816303.481355 5684 ssl_transport_security.cc:1466] Could not load root certificates.

E0000 00:00:1770816303.488018 5684 ssl_transport_security.cc:886] Could not load any root certificate.

E0000 00:00:1770816303.488263 5684 ssl_transport_security.cc:2576] Cannot load server root certificates.

E0000 00:00:1770816303.488506 5684 ssl_credentials.cc:212] Handshaker factory creation failed with TSI_INVALID_ARGUMENT

The error appears to indicate that gRPC requires root certificates to be installed. However, according to this GitHub issue, the gRPC library now loads certificates automatically:

https://github.com/grpc/grpc/issues/25533

However, I continue to receive this error. I tried installing the certificates manually as shown in the code below, after which the number of errors decreased, and I get the following output

WARNING: All log messages before absl::InitializeLog() is called are written to STDERR

E0000 00:00:1770816360.263513 19664 ssl_transport_security.cc:886] Could not load any root certificate.

E0000 00:00:1770816360.263836 19664 ssl_transport_security.cc:2576] Cannot load server root certificates.

E0000 00:00:1770816360.264067 19664 ssl_credentials.cc:212] Handshaker factory creation failed with TSI_INVALID_ARGUMENT

As you can see, the problem with loading root certificates still persists. What could be the problem?

Here's my code:

#include 
#include 

std::string utf8Encode(const std::wstring& wstr)
{
    if (wstr.empty())
        return std::string();

    int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
        NULL, 0, NULL, NULL);
    std::string strTo(sizeNeeded, 0);
    WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
        &strTo[0], sizeNeeded, NULL, NULL);
    return strTo;
}

using namespace grpc;

SslCredentialsOptions getSslOptions()
{
    // Fetch root certificate as required on Windows (s. issue 25533).
    SslCredentialsOptions result;

    // Open root certificate store.
    HANDLE hRootCertStore = CertOpenSystemStoreW(NULL, L"ROOT");
    if (!hRootCertStore)
        return result;

    // Get all root certificates.
    PCCERT_CONTEXT pCert = NULL;
    while ((pCert = CertEnumCertificatesInStore(hRootCertStore, pCert)) != NULL)
    {
        // Append this certificate in PEM formatted data.
        DWORD size = 0;
        CryptBinaryToStringW(pCert->pbCertEncoded, pCert->cbCertEncoded,
            CRYPT_STRING_BASE64HEADER, NULL, &size);
        std::vector pem(size);
        CryptBinaryToStringW(pCert->pbCertEncoded, pCert->cbCertEncoded,
            CRYPT_STRING_BASE64HEADER, pem.data(), &size);

        result.pem_root_certs += utf8Encode(pem.data());
    }

    CertCloseStore(hRootCertStore, 0);
    return result;
}

int main()
{
    std::cout << "gRPC version: " << grpc::Version() << std::endl;

    grpc::SslCredentialsOptions ssl_opts = getSslOptions();
    auto channel = grpc::CreateChannel("grpcb.in:9001", grpc::SslCredentials(ssl_opts));

    return 0;
}
c++ windows grpc