apache/shenyu · critical · ShenyuException
zookeeper url is empty
Error message
zookeeper url is empty
What it means
ZookeeperConfiguration.zookeeperClient builds the ZookeeperClient bean from ZookeeperProperties. Before connecting it verifies that the configured zookeeper URL has text; if it is null/blank it throws ShenyuException('zookeeper url is empty'). ZooKeeper is a mandatory dependency for the zookeeper sync mode, so the app cannot proceed without it.
Solutions
- Set the zookeeper URL in configuration: shenyu.sync.zookeeper.url=127.0.0.1:2181
- Verify the exact property path matches the version's ZookeeperProperties binding (zookeeper.url inside the config object)
- Ensure the environment variable or ConfigMap providing the URL is actually mounted and named correctly
- Check application logs/startup binding to confirm the property was read
Example fix
// before (application.yml)
shenyu:
sync:
zookeeper:
url:
// after
shenyu:
sync:
zookeeper:
url: 127.0.0.1:2181 Defensive patterns
Strategy: validation
Validate before calling
String url = env.getProperty("shenyu.sync.zookeeper.url");
if (url == null || url.isBlank()) {
throw new IllegalStateException("shenyu.sync.zookeeper.url must be set");
} Try / catch
try {
context = SpringApplication.run(App.class, args);
} catch (Exception e) {
if (e.getCause() instanceof ShenyuException && e.getMessage().contains("zookeeper url is empty")) {
log.error("Set shenyu.sync.zookeeper.url before enabling zookeeper sync");
}
throw e;
} Prevention
- Always configure shenyu.sync.zookeeper.url when using zookeeper sync
- Supply it via env var/ConfigMap in container deployments
- Verify property key spelling against the properties class
- Fail fast in CI config checks before deployment
When it happens
Trigger: Starting the application with shenyu.sync.zookeeper.url unset or empty while the zookeeper data-sync/registration mode is enabled.
Common situations: Missing property in application.yml when switching sync modes, environment variable not set in Docker/Kubernetes, property name typo so the value never binds.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- shenyu.jwt.secretKey is not configured. In a multi-instance…
- clientConfig must config " + getClientName() + " properties
- grpc client must config the contextPath, ipAndPort
- is malformed
- illegal param, serverLists configuration required if…
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/7c1a55e1a4117071.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-infra/shenyu-infra-zookeeper/src/main/java/org/apache/shenyu/infra/zookeeper/autoconfig/ZookeeperConfiguration.java:68
private static final Integer DEFAULT_BASE_SLEEP_TIME = 1000;
private static final Integer DEFAULT_MAX_SLEEP_TIME = Integer.MAX_VALUE;
private static final Integer DEFAULT_MAX_RETRIES = 3;
/**
* Zookeeper client bean.
*
* @param zookeeperProperties zookeeper properties
* @return ZookeeperClient
*/
@Bean
@ConditionalOnMissingBean(ZookeeperClient.class)
public ZookeeperClient zookeeperClient(final ZookeeperProperties zookeeperProperties) {
ZookeeperConfig config = zookeeperProperties.getZookeeper();
if (!StringUtils.hasText(config.getUrl())) {
throw new ShenyuException("zookeeper url is empty");
}
if (Objects.isNull(config.getBaseSleepTimeMilliseconds())) {
config.setBaseSleepTimeMilliseconds(DEFAULT_BASE_SLEEP_TIME);
}
if (Objects.isNull(config.getMaxSleepTimeMilliseconds())) {
config.setMaxSleepTimeMilliseconds(DEFAULT_MAX_SLEEP_TIME);
}
if (Objects.isNull(config.getMaxRetries())) {
config.setMaxRetries(DEFAULT_MAX_RETRIES);
}
if (Objects.isNull(config.getSessionTimeoutMilliseconds())) {
config.setSessionTimeoutMilliseconds(DEFAULT_SESSION_TIMEOUT);
}
if (Objects.isNull(config.getConnectionTimeoutMilliseconds())) {
config.setConnectionTimeoutMilliseconds(DEFAULT_CONNECT_TIMEOUT);
}
LOG.info("init zookeeper client, config: {}", config);View on GitHub (pinned to 567142e072)