quarkusio/quarkus · error · UnsupportedOperationException

JDK provider does not support %s failure behavior

Error message

JDK provider does not support %s failure behavior

What it means

When the JDK SSL provider is used, Netty's ALPN support (here the Quarkus native substitution's toNegotiator) can only map SelectorFailureBehavior.FATAL_ALERT and NO_ADVERTISE onto JDK TLS semantics. Any other selector failure behavior — i.e. ACCEPT — is unrepresentable, so an UnsupportedOperationException is thrown.

Source

Thrown at extensions/netty/runtime/src/main/java/io/quarkus/netty/runtime/graal/NettySubstitutions.java:365

            case ALPN:
                if (isServer) {
                    // GRAAL RC9 bug: https://github.com/oracle/graal/issues/813
                    //                switch(config.selectorFailureBehavior()) {
                    //                case FATAL_ALERT:
                    //                    return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
                    //                case NO_ADVERTISE:
                    //                    return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
                    //                default:
                    //                    throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
                    //                    .append(config.selectorFailureBehavior()).append(" failure behavior").toString());
                    //                }
                    SelectorFailureBehavior behavior = config.selectorFailureBehavior();
                    if (behavior == SelectorFailureBehavior.FATAL_ALERT) {
                        return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
                    } else if (behavior == SelectorFailureBehavior.NO_ADVERTISE) {
                        return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
                    } else {
                        throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
                                .append(config.selectorFailureBehavior()).append(" failure behavior").toString());
                    }
                } else {
                    switch (config.selectedListenerFailureBehavior()) {
                        case ACCEPT:
                            return new JdkAlpnApplicationProtocolNegotiator(false, config.supportedProtocols());
                        case FATAL_ALERT:
                            return new JdkAlpnApplicationProtocolNegotiator(true, config.supportedProtocols());
                        default:
                            throw new UnsupportedOperationException(new StringBuilder("JDK provider does not support ")
                                    .append(config.selectedListenerFailureBehavior()).append(" failure behavior")
                                    .toString());
                    }
                }
            default:
                throw new UnsupportedOperationException(
                        new StringBuilder("JDK provider does not support ").append(config.protocol())
                                .append(" protocol")

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change selectorFailureBehavior to FATAL_ALERT or NO_ADVERTISE in the ApplicationProtocolConfig.
  2. Use the OpenSSL provider, which supports all SelectorFailureBehavior values.
  3. Create two configs: one for JDK provider constraints and one for OpenSSL.

Example fix

// before
ApplicationProtocolConfig apn = new ApplicationProtocolConfig(
    ApplicationProtocolConfig.Protocol.ALPN,
    ApplicationProtocolConfig.SelectorFailureBehavior.ACCEPT,
    ApplicationProtocolConfig.SelectedListenerFailureBehavior.FATAL_ALERT,
    HttpVersion.HTTP_2.protocolName());
// after
ApplicationProtocolConfig apn = new ApplicationProtocolConfig(
    ApplicationProtocolConfig.Protocol.ALPN,
    ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,
    ApplicationProtocolConfig.SelectedListenerFailureBehavior.FATAL_ALERT,
    HttpVersion.HTTP_2.protocolName());
Defensive patterns

Strategy: validation

Validate before calling

if (config.selectorFailureBehavior() == SelectorFailureBehavior.ACCEPT) {
    throw new IllegalArgumentException("SelectorFailureBehavior.ACCEPT unsupported with JDK provider");
}

Try / catch

try {
    ctx = builder.build();
} catch (UnsupportedOperationException e) {
    if (e.getMessage().contains("failure behavior")) {
        ctx = builderWithFixedAlpnConfig().build();
    } else { throw e; }
}

Prevention

When it happens

Trigger: ApplicationProtocolConfig with protocol ALPN, selectorFailureBehavior() returning SelectorFailureBehavior.ACCEPT (anything other than FATAL_ALERT/NO_ADVERTISE), while using SslProvider.JDK — hit during SslContext construction.

Common situations: Sharing an ApplicationProtocolConfig between OpenSSL and JDK providers where ACCEPT behavior was chosen; upgrading/migrating from tcnative to JDK provider without revisiting ALPN config; defaulting selectors in copied HTTP/2 bootstrap code.

Related errors


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