grpc/grpc-java · error · IllegalArgumentException

Want certificate verification but got null or empty certific

Error message

Want certificate verification but got null or empty certificates

What it means

checkTrusted validates the certificate chain only when it is non-null and non-empty; a null or empty chain is treated as a caller bug, not a certificate problem, so it throws IllegalArgumentException. If the caller intended to skip peer verification it should configure the manager accordingly rather than pass an empty chain.

Source

Thrown at util/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java:156

    // If found, use that as the delegate trust manager.
    for (TrustManager tm : tms) {
      if (tm instanceof X509ExtendedTrustManager) {
        delegateManager = (X509ExtendedTrustManager) tm;
        break;
      }
    }
    if (delegateManager == null) {
      throw new CertificateException(
          "Failed to find X509ExtendedTrustManager with default TrustManager algorithm "
              + TrustManagerFactory.getDefaultAlgorithm());
    }
    return delegateManager;
  }

  private void checkTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine,
      Socket socket, boolean checkingServer) throws CertificateException {
    if (chain == null || chain.length == 0) {
      throw new IllegalArgumentException(
          "Want certificate verification but got null or empty certificates");
    }
    if (sslEngine == null && socket == null) {
      throw new CertificateException(NOT_ENOUGH_INFO_MESSAGE);
    }
    if (this.verification != Verification.INSECURELY_SKIP_ALL_VERIFICATION) {
      X509ExtendedTrustManager currentDelegateManager = this.delegateManager;
      if (currentDelegateManager == null) {
        throw new CertificateException("No trust roots configured");
      }
      if (checkingServer) {
        String algorithm = this.verification == Verification.CERTIFICATE_AND_HOST_NAME_VERIFICATION
            ? "HTTPS" : "";
        if (sslEngine != null) {
          SSLParameters sslParams = sslEngine.getSSLParameters();
          sslParams.setEndpointIdentificationAlgorithm(algorithm);
          sslEngine.setSSLParameters(sslParams);
          currentDelegateManager.checkServerTrusted(chain, authType, sslEngine);

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Pass a non-empty X509Certificate[] chain obtained from the peer (e.g., sslEngine.getSession().getPeerCertificates()).
  2. If you intentionally want to skip verification, configure Verification.INSECURELY_SKIP_ALL_VERIFICATION via useInsecureSkipVerify() instead of passing an empty chain.
  3. Check that the peer is actually presenting a certificate (client certs require setNeedClientAuth on server side).
  4. Guard the call: only invoke checkTrusted paths when the session has peer certificates.

Example fix

// before
trustManager.checkServerTrusted(new X509Certificate[0], "TLS", engine);

// after
X509Certificate[] chain = (X509Certificate[]) engine.getSession().getPeerCertificates();
if (chain != null && chain.length > 0) {
  trustManager.checkServerTrusted(chain, "TLS", engine);
}
Defensive patterns

Strategy: validation

Validate before calling

if (chain == null || chain.length == 0) {
  throw new IllegalArgumentException("Peer presented no certificates; cannot verify");
}
trustManager.checkServerTrusted(chain, authType, sslEngine);

Type guard

static boolean hasCertificates(X509Certificate[] chain) {
  return chain != null && chain.length > 0;
}

Try / catch

try {
  trustManager.checkServerTrusted(chain, authType, sslEngine);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("null or empty certificates")) {
    throw new CertificateException("Peer provided no certificate chain", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling checkClientTrusted or checkServerTrusted (any overload) with chain == null or chain.length == 0 — e.g., an upstream handshake passed no peer certificates, or a test harness passed an empty array.

Common situations: Tests constructing empty X509Certificate[] arrays; integration with an SSL layer that surfaced no peer certificates (anonymous cipher suites, misconfigured keystore); proxy termination stripping the peer chain; mistakenly calling verify with no certs fetched from a session.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/3b53cc3c6c4f5f82. Report an issue: GitHub.