apache/shenyu · error · ShenyuException

shenyu.register.serverLists can not be null.

Error message

shenyu.register.serverLists can not be null.

What it means

ConsulInstanceRegisterRepository.init validates shenyu.register.serverLists before constructing the ConsulClient; a blank value means the gateway has nowhere to register/select instances, so a ShenyuException is thrown during repository initialization.

Solutions

  1. Set shenyu.register.serverLists to the Consul address, e.g. http://localhost:8500
  2. Confirm the config file/profile containing the property is actually loaded
  3. Verify you are using the consul registerType/registry module intentionally
  4. Check property name against the module's documentation for your version

Example fix

// before
shenyu:
  register:
    registerType: consul
# serverLists missing
// after
shenyu:
  register:
    registerType: consul
    serverLists: http://localhost:8500
Defensive patterns

Strategy: validation

Validate before calling

String sl = config.getServerLists(); if (sl == null || sl.isBlank()) throw new IllegalArgumentException("set shenyu.register.serverLists for consul");

Try / catch

try { repository.init(); } catch (ShenyuException e) { log.error("consul register config invalid: {}", e.getMessage()); System.exit(1); }

Prevention

When it happens

Trigger: init() (e.g. from testSelectInstancesAndWatcher or Spring wiring) runs with shenyu.register.serverLists unset or empty in the register config.

Common situations: Using the consul registry module without adding shenyu.register.serverLists to application.yml; config file not loaded (wrong profile); property renamed/moved between versions.

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


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

Appendix: source

Thrown at shenyu-registry/shenyu-registry-consul/src/main/java/org/apache/shenyu/registry/consul/ConsulInstanceRegisterRepository.java:105

    private TtlScheduler ttlScheduler;

    private final Map<String, List<InstanceEntity>> watcherInstanceRegisterMap = new ConcurrentHashMap<>();

    private final Set<String> watchSelectKeySet = ConcurrentHashMap.newKeySet();

    @Override
    public void init(final RegisterConfig config) {
        final Properties props = config.getProps();
        this.checkTtl = props.getProperty("checkTtl", "5");
        this.token = props.getProperty("token", "");
        this.waitTime = props.getProperty("waitTime", "30");
        this.watchDelay = props.getProperty("watchDelay", "5");
        this.tags = props.getProperty("tags");

        final String serverList = config.getServerLists();
        if (StringUtils.isBlank(serverList)) {
            throw new ShenyuException("shenyu.register.serverLists can not be null.");
        }
        final String[] addresses = serverList.split(":");
        if (addresses.length != 2) {
            throw new ShenyuException("shenyu.register.serverLists formatter is not incorrect.");
        }
        consulClient = new ConsulClient(addresses[0], Integer.parseInt(addresses[1]));
        this.ttlScheduler = new TtlScheduler(Integer.parseInt(checkTtl), consulClient);
        Runtime.getRuntime().addShutdownHook(new Thread(this::close));
    }

    @Override
    public void persistInstance(final InstanceEntity instance) {
        String instanceNodeName = buildInstanceNodeName(instance);
        this.newService = new NewService();
        newService.setName(instance.getAppName());
        newService.setId(String.join("-", instance.getAppName(), instanceNodeName));
        newService.setAddress(instance.getHost());
        newService.setPort(instance.getPort());

View on GitHub (pinned to 567142e072)