grpc/grpc-java · error · RuntimeException

TLS ALPN negotiation failed with protocols: ${protocols}

Error message

TLS ALPN negotiation failed with protocols: ${protocols}

What it means

OkHttpProtocolNegotiator.negotiate forces the SSL handshake and then reads the ALPN/ NPN negotiated protocol; if the socket reports no selected protocol it throws RuntimeException naming the configured protocols. This means TLS succeeded but the peers did not agree on an application protocol (e.g. h2).

Source

Thrown at okhttp/src/main/java/io/grpc/okhttp/OkHttpProtocolNegotiator.java:106

  /**
   * Start and wait until the negotiation is done, returns the negotiated protocol.
   *
   * @throws IOException if an IO error was encountered during the handshake.
   * @throws RuntimeException if the negotiation completed, but no protocol was selected.
   */
  public String negotiate(
      SSLSocket sslSocket, String hostname, @Nullable List<Protocol> protocols) throws IOException {
    if (protocols != null) {
      configureTlsExtensions(sslSocket, hostname, protocols);
    }
    try {
      // Force handshake.
      sslSocket.startHandshake();

      String negotiatedProtocol = getSelectedProtocol(sslSocket);
      if (negotiatedProtocol == null) {
        throw new RuntimeException("TLS ALPN negotiation failed with protocols: " + protocols);
      }
      return negotiatedProtocol;
    } finally {
      platform.afterHandshake(sslSocket);
    }
  }

  /** Configure TLS extensions. */
  protected void configureTlsExtensions(
      SSLSocket sslSocket, String hostname, List<Protocol> protocols) {
    platform.configureTlsExtensions(sslSocket, hostname, protocols);
  }

  /** Returns the negotiated protocol, or null if no protocol was negotiated. */
  public String getSelectedProtocol(SSLSocket socket) {
    return platform.getSelectedProtocol(socket);
  }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Ensure the server supports HTTP/2 with ALPN and advertises h2
  2. Upgrade to a JDK with ALPN support (8u251+ or 11+), or install Conscrypt as the security provider
  3. Verify no intermediary (LB/proxy) strips ALPN extension
  4. If using custom SSLSocketFactory/sslSocket override, make sure it doesn't disable ALPN

Example fix

// before
SSLSocket socket = factory.createSocket(...); // JDK without ALPN
// after
Security.insertProviderAt(Conscrypt.newProvider(), 1);
SSLContext ctx = SSLContext.getInstance("TLS", "Conscrypt");
Defensive patterns

Strategy: fallback

Validate before calling

// detect JDK ALPN availability
boolean alpnOk = Platform.get().getTlsExtensionType() != TlsExtensionType.NONE;

Try / catch

try { stub.unaryCall(req); } catch (RuntimeException e) { if (e.getMessage().contains("ALPN negotiation failed")) { installConscryptAndRetry(); } throw e; }

Prevention

When it happens

Trigger: Server does not support ALPN or advertises no protocol gRPC requires (h2), client protocol list mismatched, or Android/JDK version lacking ALPN support so getSelectedProtocol returns null.

Common situations: Old JDK 7/8 without ALPN support, servers without HTTP/2 enabled, load balancers stripping ALPN, Android versions needing Google Play Services provider.

Understand the failure class

Related errors


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