apache/shenyu · error · ShenyuException
The sslCrtAndKeys can not be null
Error message
The sslCrtAndKeys can not be null
What it means
ShenyuSniAsyncMapping's parameterized constructor builds SNI SSL providers from a list of certificate/key files; a null or empty list means no SNI mapping could be created, so it throws ShenyuException('The sslCrtAndKeys can not be null'). The gateway needs at least one cert/key pair to construct Http11SslContextSpec entries for domain-based TLS routing.
Solutions
- Configure at least one ssl cert/key pair (keyCertChainFile + keyFile) under the shenyu SNI settings before constructing the mapping.
- Verify the file paths exist and are readable — next failure after an empty list is typically file-not-found.
- Check the code path building the list (config parsing/filtering) for why it returned empty.
- If SNI is not needed, avoid constructing ShenyuSniAsyncMapping with the empty list rather than passing it defensively.
Example fix
// before
List<SslCrtAndKeyFile> certs = sniConfig.getCerts(); // may be empty
new ShenyuSniAsyncMapping(certs);
// after
if (certs != null && !certs.isEmpty()) {
new ShenyuSniAsyncMapping(certs);
} else {
LOG.warn("SNI disabled: no certificates configured");
} Defensive patterns
Strategy: validation
Validate before calling
if (sslCrtAndKeys == null || sslCrtAndKeys.isEmpty()) {
throw new IllegalArgumentException("at least one SNI cert/key pair is required");
} Type guard
boolean hasCerts(List<SslCrtAndKeyFile> l) {
return l != null && !l.isEmpty();
} Try / catch
try {
new ShenyuSniAsyncMapping(certs);
} catch (ShenyuException e) {
LOG.error("SNI init failed: {}", e.getMessage());
} Prevention
- Validate SNI cert config at startup before any SslProvider construction.
- Log the number of cert entries parsed so empty resolution is visible.
- Verify cert/key file paths exist and are readable in the target environment.
When it happens
Trigger: new ShenyuSniAsyncMapping(list) where list is null or isEmpty() — e.g. shenyu.sni.* configuration resolved to zero certificate entries.
Common situations: SNI enabled in bootstrap config but no crt/key file paths configured; a config loader returning an empty list when file globs match nothing; property names mistyped so cert entries aren't parsed.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Can not find shenyuSniAsyncMapping bean
- At least one certificate is required
- Cannot read the sni mod
- Can not read cert and key from default secret
- dynamic: result.getMessage() from…
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/b552bbd926bdf3b4.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-common/src/main/java/org/apache/shenyu/common/config/ssl/ShenyuSniAsyncMapping.java:48
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
/**
* Sni async map, can be used to dynamically configure ssl certificates.
*/
public class ShenyuSniAsyncMapping implements AsyncMapping<String, SslProvider> {
private final ConcurrentHashMap<String, SslProvider> sslProviderMap;
public ShenyuSniAsyncMapping() {
this.sslProviderMap = new ConcurrentHashMap<>();
}
public ShenyuSniAsyncMapping(final List<SslCrtAndKeyFile> sslCrtAndKeys) {
if (Objects.isNull(sslCrtAndKeys) || sslCrtAndKeys.isEmpty()) {
throw new ShenyuException("The sslCrtAndKeys can not be null");
}
this.sslProviderMap = new ConcurrentHashMap<>();
sslCrtAndKeys.forEach(sslCrtAndKey -> {
Http11SslContextSpec sslContextSpec = Http11SslContextSpec.forServer(new File(sslCrtAndKey.getKeyCertChainFile()),
new File(sslCrtAndKey.getKeyFile()));
SslProvider sslProvider = SslProvider.builder().sslContext(sslContextSpec).build();
this.sslProviderMap.put(sslCrtAndKey.getDomain(), sslProvider);
});
}
/**
* Add SslProvider by domain.
*
* @param domain domain
* @param sslProvider SslProvider
*/
public void addSslProvider(final String domain, final SslProvider sslProvider) {
sslProviderMap.put(domain, sslProvider);View on GitHub (pinned to 567142e072)