quarkusio/quarkus · error · IllegalArgumentException

Could not find Jetty NPN/ALPN or Conscrypt as installed JDK

Error message

Could not find Jetty NPN/ALPN or Conscrypt as installed JDK providers

What it means

This is a GraalVM native-image substitution for Netty's GrpcSslContexts.configure. In native mode Netty's JDK-provider lookup cannot find Jetty NPN/ALPN or Conscrypt, so the substituted findJdkProvider returns null and the code throws IllegalArgumentException. TLS over gRPC with SslProvider.JDK cannot be set up in the native image.

Source

Thrown at extensions/grpc-common/runtime/src/main/java/io/quarkus/grpc/common/runtime/graal/GrpcNettySubstitutions.java:41

    @Substitute
    static void logSslEngineDetails(Level level, ChannelHandlerContext ctx, String msg, Throwable t) {
        Logger log = Logger.getLogger("io.grpc.netty.ProtocolNegotiators");
        if (log.isLoggable(level)) {
            log.log(level, msg + "\nNo SSLEngine details available!", t);
        }
    }
}

@TargetClass(className = "io.grpc.netty.GrpcSslContexts")
final class Target_io_grpc_netty_GrpcSslContexts {

    @Substitute
    public static SslContextBuilder configure(SslContextBuilder builder, SslProvider provider) {
        switch (provider) {
            case JDK: {
                Provider jdkProvider = findJdkProvider();
                if (jdkProvider == null) {
                    throw new IllegalArgumentException(
                            "Could not find Jetty NPN/ALPN or Conscrypt as installed JDK providers");
                }
                return configure(builder, jdkProvider);
            }
            default:
                throw new IllegalArgumentException("Unsupported provider: " + provider);
        }
    }

    @Alias
    private static Provider findJdkProvider() {
        return null;
    }

    @Alias
    public static SslContextBuilder configure(SslContextBuilder builder, Provider jdkProvider) {
        return null;
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add Conscrypt as a dependency and register it for reflection/native so it is found as a JDK provider
  2. Configure gRPC TLS to use the OpenSSL provider instead of JDK
  3. Avoid the Netty gRPC JDK SSL path in native mode (e.g. use Quarkus-managed TLS config)

Example fix

// before
GrpcSslContexts.forClient().trustManager(ca).build(); // defaults to JDK provider in native
// after
GrpcSslContexts.configure(GrpcSslContexts.forClient().trustManager(ca),
        SslProvider.OPENSSL).build();
Defensive patterns

Strategy: fallback

Validate before calling

Provider p = Security.getProvider("Conscrypt");
if (p == null && isNativeImage()) {
    LOG.warn("No ALPN/Conscrypt JDK provider; use OpenSSL provider for native TLS");
}

Try / catch

try {
    GrpcSslContexts.configure(builder, SslProvider.JDK);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Jetty NPN/ALPN")) {
        return GrpcSslContexts.configure(builder, SslProvider.OPENSSL);
    }
    throw e;
}

Prevention

When it happens

Trigger: Building/running a native-image application that uses gRPC over TLS with the JDK SSL provider, when neither Conscrypt nor Jetty ALPN is available as a JDK provider in the image.

Common situations: Native build of a TLS-enabled gRPC client/server without adding Conscrypt; upgrading to native image where JDK ALPN bootclasspath hooks no longer exist.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/821d022cfe2c6ae7. Report an issue: GitHub.