apache/shenyu · error · ShenyuException

Can not find shenyuSniAsyncMapping bean

Error message

Can not find shenyuSniAsyncMapping bean

What it means

When SNI is enabled (shenyu.server.netty.sni.enabled=true), the Netty web server factory must be supplied with a ShenyuSniAsyncMapping bean that resolves SSL contexts per SNI hostname. If SNI is on but no such bean exists in the context, startup throws this ShenyuException.

Solutions

  1. Add the shenyu-spring-boot-starter-k8s dependency which registers the ShenyuSniAsyncMapping bean
  2. Or disable SNI (shenyu.server.netty.sni.enabled=false) if you don't need per-host certificates
  3. Or manually define a ShenyuSniAsyncMapping bean via shenyuSniAsyncMappingProvider-compatible @Bean

Example fix

// before (pom.xml)
<!-- only gateway starter -->
// after
<dependency>
  <groupId>org.apache.shenyu</groupId>
  <artifactId>shenyu-spring-boot-starter-k8s</artifactId>
  <version>${shenyu.version}</version>
</dependency>
Defensive patterns

Strategy: validation

Validate before calling

boolean sniEnabled = env.getProperty("shenyu.server.netty.sni.enabled", Boolean.class, false);
boolean k8sStarterPresent = ClassUtils.isPresent(
    "org.apache.shenyu.springboot.starter.k8s.IngressControllerConfiguration",
    ShenyuNettyWebServerConfiguration.class.getClassLoader());
if (sniEnabled && "k8s".equals(env.getProperty("shenyu.server.netty.sni.mod")) && !k8sStarterPresent) {
    throw new IllegalStateException("SNI k8s mode requires the shenyu-spring-boot-starter-k8s module");
}

Try / catch

try {
    context = SpringApplication.run(GatewayApplication.class, args);
} catch (Exception e) {
    if (rootCauseOf(e, ShenyuException.class).map(x -> x.getMessage().contains("shenyuSniAsyncMapping")).orElse(false)) {
        log.error("Enable SNI only with the k8s starter or define a ShenyuSniAsyncMapping bean");
    } else throw e;
}

Prevention

When it happens

Trigger: Enabling shenyu.server.netty.sni.enabled=true while using 'k8s' (auto-discovery) mode without the shenyu-spring-boot-starter-k8s module (which provides the bean), or the bean was excluded/filtered from component scanning.

Common situations: Turning on SNI in a plain gateway deployment that lacks the k8s starter; copying config from a Kubernetes deployment guide into a non-k8s environment; custom build that stripped IngressController auto-configuration.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/614eeffc24e7cb10. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/netty/ShenyuNettyWebServerConfiguration.java:100

     * @param shenyuSniAsyncMappingProvider shenyuSniAsyncMapping
     * @param tcpSslContextSpecs default tcpSslContextSpecs
     * @return the netty reactive web server factory
     */
    @Bean
    @ConditionalOnProperty(value = "shenyu.netty.http.web-server-factory-enabled", havingValue = "true", matchIfMissing = true)
    public NettyReactiveWebServerFactory nettyReactiveWebServerFactory(final ObjectProvider<NettyHttpProperties> properties,
                                                                       final ObjectProvider<ShenyuSniAsyncMapping> shenyuSniAsyncMappingProvider,
                                                                       final ObjectProvider<TcpSslContextSpec> tcpSslContextSpecs) {
        NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory();
        NettyHttpProperties nettyHttpProperties = Optional.ofNullable(properties.getIfAvailable()).orElse(new NettyHttpProperties());
        webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer(nettyHttpProperties, httpServer -> {
            HttpServer server = httpServer;
            // Configure sni certificates
            NettyHttpProperties.SniProperties sniProperties = nettyHttpProperties.getSni();
            if (sniProperties.getEnabled()) {
                ShenyuSniAsyncMapping shenyuSniAsyncMapping = shenyuSniAsyncMappingProvider.getIfAvailable();
                if (Objects.isNull(shenyuSniAsyncMapping)) {
                    throw new ShenyuException("Can not find shenyuSniAsyncMapping bean");
                }
                if ("manual".equals(sniProperties.getMod())) {
                    List<SslCrtAndKeyFile> sslCrtAndKeyFiles = sniProperties.getCertificates();
                    if (CollectionUtils.isEmpty(sslCrtAndKeyFiles)) {
                        throw new ShenyuException("At least one certificate is required");
                    }

                    // Use the first certificate as the default certificate (this default certificate will not actually be used)
                    List<SslCrtAndKeyFile> certificates = sslCrtAndKeyFiles;
                    for (SslCrtAndKeyFile certificate : certificates) {
                        try {
                            shenyuSniAsyncMapping.addSslCertificate(certificate);
                        } catch (IOException e) {
                            LOG.error("add certificate error", e);
                        }
                    }

                    SslCrtAndKeyFile defaultCert = certificates.get(0);

View on GitHub (pinned to 567142e072)