apache/shenyu · error · ShenyuAdminException

before start ProxySelector you need init DiscoveryId=

Error message

before start ProxySelector you need init DiscoveryId=%s

What it means

APDiscoveryProcessor.createProxySelector resolves the ShenyuInstanceRegisterRepository via discoveryHandlerDTO.getDiscoveryId(); when it is null (the discovery handler was never initialized/created first) it throws ShenyuAdminException telling you to init DiscoveryId before starting a ProxySelector. Discovery setup must precede proxy-selector setup.

Solutions

  1. Create/initialize the Discovery configuration first so its DiscoveryId exists, then create the ProxySelector
  2. If importing, reorder the import so discovery configs are processed before proxy selectors
  3. Verify the discoveryId in the DTO matches an existing discovery record

Example fix

// before
processor.createProxySelector(discoveryHandlerDTO, proxySelectorDTO); // discoveryId not initialized
// after
processor.createDiscovery(discoveryDTO);            // init discovery first
processor.createDiscoveryHandler(discoveryHandlerDTO);
processor.createProxySelector(discoveryHandlerDTO, proxySelectorDTO);
Defensive patterns

Strategy: validation

Validate before calling

if (discoveryServiceRepo.get(discoveryHandlerDTO.getDiscoveryId()) == null) {
    throw new IllegalStateException("initialize Discovery first, discoveryId=" + discoveryHandlerDTO.getDiscoveryId());
}

Try / catch

try {
    processor.createProxySelector(handlerDTO, selectorDTO);
} catch (ShenyuAdminException e) {
    if (e.getMessage().startsWith("before start ProxySelector you need init")) { /* create discovery then retry */ }
}

Prevention

When it happens

Trigger: Calling createProxySelector with a discoveryHandlerDTO whose discoveryId has no matching discovery configuration/processor state — i.e. creating the proxy selector before the discovery config was saved/processed.

Common situations: Importing config exports out of order (proxy selectors before discovery configs); API automation creating selectors without the preceding discovery creation call; deleted discovery left referenced by a selector.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/discovery/APDiscoveryProcessor.java:53

import java.util.Set;

public class APDiscoveryProcessor extends AbstractDiscoveryProcessor {

    /**
     * DefaultDiscoveryProcessor.
     *
     * @param discoveryUpstreamMapper discoveryUpstreamMapper
     */
    public APDiscoveryProcessor(final DiscoveryUpstreamMapper discoveryUpstreamMapper) {
        super(discoveryUpstreamMapper);
    }

    @Override
    public void createProxySelector(final DiscoveryHandlerDTO discoveryHandlerDTO, final ProxySelectorDTO proxySelectorDTO) {
        ShenyuInstanceRegisterRepository shenyuDiscoveryService = getShenyuDiscoveryService(discoveryHandlerDTO.getDiscoveryId());
        String key = super.buildProxySelectorKey(discoveryHandlerDTO.getListenerNode());
        if (Objects.isNull(shenyuDiscoveryService)) {
            throw new ShenyuAdminException(String.format("before start ProxySelector you need init DiscoveryId=%s", discoveryHandlerDTO.getDiscoveryId()));
        }
        Set<String> cacheKey = getCacheKey(discoveryHandlerDTO.getDiscoveryId());
        if (Objects.nonNull(cacheKey) && cacheKey.contains(key)) {
            LOG.info("shenyu discovery has watcher key = {}", key);
            super.addDiscoverySyncDataListener(discoveryHandlerDTO, proxySelectorDTO);
            return;
        }
        LOG.info("shenyu discovery id {} watch key = {}", discoveryHandlerDTO.getId(), key);
        final DataChangedEventListener discoveryDataChangedEventListener = getDiscoveryDataChangedEventListener(discoveryHandlerDTO, proxySelectorDTO);
        shenyuDiscoveryService.watchInstances(key, (selectKey, selectValue, event) -> {
            LOG.info("shenyu discovery receive watch discovery id {} key = {}, value = {}, event = {}", discoveryHandlerDTO.getId(), selectKey, selectValue, event);
            if (event.equals(ChangedEventListener.Event.ADDED)) {
                discoveryDataChangedEventListener.onChange(new DiscoveryDataChangedEvent(selectKey, selectValue, DiscoveryDataChangedEvent.Event.ADDED));
            } else if (event.equals(ChangedEventListener.Event.UPDATED)) {
                discoveryDataChangedEventListener.onChange(new DiscoveryDataChangedEvent(selectKey, selectValue, DiscoveryDataChangedEvent.Event.UPDATED));
            } else if (event.equals(ChangedEventListener.Event.DELETED)) {
                discoveryDataChangedEventListener.onChange(new DiscoveryDataChangedEvent(selectKey, selectValue, DiscoveryDataChangedEvent.Event.DELETED));
            } else {

View on GitHub (pinned to 567142e072)