grpc/grpc-java · error · IllegalStateException

A key manager is required

Error message

A key manager is required

What it means

TlsServerCredentials.Builder.build() requires some form of server-side private key material. If neither a certificate chain nor key managers were configured, the credentials would be unusable for TLS, so build() throws this IllegalStateException.

Solutions

  1. Call keyManager(KeyManager...) or keyManager(String certChain, String privateKey) to supply the server identity
  2. Or call certificateChain(...) alongside a private key configuration
  3. If the endpoint should not be a TLS server, use InsecureServerCredentials or TlsChannelCredentials for clients instead

Example fix

// before
TlsServerCredentials.newBuilder()
    .trustManager(trustCerts) // only client-auth trust
    .build(); // throws
// after
TlsServerCredentials.newBuilder()
    .keyManager(serverCertChainPem, serverPrivateKeyPem)
    .trustManager(trustCerts)
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if (certChain == null && keyManagers == null) {
  throw new IllegalArgumentException("TLS server needs keyManager or certificateChain");
}

Try / catch

try {
  creds = tlsBuilder.build();
} catch (IllegalStateException e) {
  throw new ConfigException("TLS server credentials incomplete: provide keyManager", e);
}

Prevention

When it happens

Trigger: Building TlsServerCredentials without calling keyManager(...) and without certificateChain(...) — i.e. relying only on trustManagers (client auth settings) or no TLS material at all.

Common situations: Configuring mutual TLS and only setting trustManagers for client verification; forgetting that TLS servers always need their own identity; porting client-side (TlsChannelCredentials) code where key material is optional.

Related errors


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

Appendix: source

Thrown at api/src/main/java/io/grpc/TlsServerCredentials.java:395

     * javax.net.ssl.X509TrustManager}.
     */
    public Builder trustManager(TrustManager... trustManagers) {
      List<TrustManager> trustManagerList = Collections.unmodifiableList(new ArrayList<>(
          Arrays.asList(trustManagers)));
      clearTrustManagers();
      this.trustManagers = trustManagerList;
      return this;
    }

    private void clearTrustManagers() {
      this.rootCertificates = null;
      this.trustManagers = null;
    }

    /** Construct the credentials. */
    public ServerCredentials build() {
      if (certificateChain == null && keyManagers == null) {
        throw new IllegalStateException("A key manager is required");
      }
      return new TlsServerCredentials(this);
    }
  }

  /** The level of authentication the server should expect from the client. */
  public enum ClientAuth {
    /** Clients will not present any identity. */
    NONE,

    /**
     * Clients are requested to present their identity, but clients without identities are
     * permitted.
     */
    OPTIONAL,

    /**
     * Clients are requested to present their identity, and are required to provide a valid

View on GitHub (pinned to 64daddc1f3)