{"record":{"id":"3b78e40569486daa","repo":"apache/shenyu","slug":"when-binding-discovery-don-t-find-selector-s","errorCode":null,"errorMessage":"when binding discovery don't find selector %s","messagePattern":"when binding discovery don't find selector (.+?)","errorType":"exception","errorClass":"ShenyuException","httpStatus":null,"severity":"error","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java","lineNumber":141,"sourceCode":"        SelectorDO selectorDO = findAndLockOnDB(discoveryConfigRegisterDTO.getSelectorName(), discoveryConfigRegisterDTO.getPluginName(), discoveryConfigRegisterDTO.getNamespaceId());\n        bindingDiscovery(discoveryConfigRegisterDTO, selectorDO);\n    }\n\n    private SelectorDO findAndLockOnDB(final String selectorName, final String pluginName, final String namespaceId) {\n        SelectorDO selectorDO = null;\n        for (int i = 0; i < 3; i++) {\n            selectorDO = selectorService.findByNameAndPluginNameAndNamespaceIdForUpdate(selectorName, pluginName, namespaceId);\n            if (Objects.nonNull(selectorDO)) {\n                return selectorDO;\n            }\n            try {\n                LOG.info(\"retry to find selector {} : {}\", selectorName, pluginName);\n                Thread.sleep(500);\n            } catch (InterruptedException e) {\n                // ignore\n            }\n        }\n        throw new ShenyuException(\"when binding discovery don't find selector \" + selectorName);\n    }\n\n    private void bindingDiscovery(final DiscoveryConfigRegisterDTO discoveryConfigRegisterDTO, final SelectorDO selectorDO) {\n        ProxySelectorDTO proxySelectorDTO = new ProxySelectorDTO();\n        proxySelectorDTO.setName(selectorDO.getSelectorName());\n        proxySelectorDTO.setId(selectorDO.getId());\n        proxySelectorDTO.setPluginName(discoveryConfigRegisterDTO.getPluginName());\n        proxySelectorDTO.setNamespaceId(selectorDO.getNamespaceId());\n        DiscoveryDO discoveryDO = discoveryMapper.selectByPluginNameAndLevelAndNamespaceIdAndType(discoveryConfigRegisterDTO.getPluginName(),\n                DiscoveryLevel.PLUGIN.getCode(), discoveryConfigRegisterDTO.getNamespaceId(), discoveryConfigRegisterDTO.getDiscoveryType());\n        if (Objects.isNull(discoveryDO)) {\n            Timestamp currentTime = new Timestamp(System.currentTimeMillis());\n            discoveryDO = DiscoveryDO.builder()\n                    .id(UUIDUtils.getInstance().generateShortUuid())\n                    .discoveryName(discoveryConfigRegisterDTO.getName())\n                    .pluginName(discoveryConfigRegisterDTO.getPluginName())\n                    .discoveryType(discoveryConfigRegisterDTO.getDiscoveryType())\n                    .discoveryLevel(DiscoveryLevel.PLUGIN.getCode())","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java#L123-L159","documentation":"DiscoveryServiceImpl.findAndLockOnDB() looks up a selector by name+plugin+namespace with a SELECT ... FOR UPDATE, retrying up to 3 times with 500ms sleeps (to tolerate registration race windows). If the selector is still absent after 3 attempts, it throws ShenyuException \"when binding discovery don't find selector <name>\". This guards registerDiscoveryConfig, which binds a discovery config to an existing selector.","triggerScenarios":"A client (typically a ShenYu client SDK registering discovery config) sends a DiscoveryConfigRegisterDTO whose selectorName+pluginName+namespaceId do not match any existing selector row — selector not yet created, wrong plugin name, wrong namespaceId, or a typo in the selector name.","commonSituations":"Client registers discovery before its selector/URI registration completes and exceeds the 3-retry (~1.5s) window; namespace mismatch after upgrading to multi-namespace ShenYu; selector created under a different plugin name; selector deleted concurrently.","solutions":["Verify the selector exists in the dashboard for the exact pluginName, selectorName and namespaceId sent in the DTO.","Ensure the client registers/creates the selector before or together with the discovery config, and correct namespaceId.","Check client configuration (plugin name, namespace) matches the server-side selector.","Server-side: increase retries/backoff in findAndLockOnDB if this is a transient registration-order race."],"exampleFix":"// before\n// client registers discovery with selectorName \"my-service\" but selector was never created\n// after\n// 1. create selector \"my-service\" for pluginName (e.g. \"divide\") in the correct namespace\n// 2. then send DiscoveryConfigRegisterDTO with matching selectorName/pluginName/namespaceId","handlingStrategy":"retry","validationCode":"// before registering discovery config, confirm the selector exists\nSelectorDO selector = selectorService.findByNameAndPluginNameAndNamespaceId(\n    dto.getSelectorName(), dto.getPluginName(), namespaceId);\nif (selector == null) {\n    throw new IllegalStateException(\"selector \" + dto.getSelectorName() + \" not found; create it first\");\n}\nregisterService.registerDiscoveryConfig(dto);","typeGuard":null,"tryCatchPattern":"try {\n    discoveryService.registerDiscoveryConfig(dto);\n} catch (ShenyuException e) {\n    if (e.getMessage().startsWith(\"when binding discovery don't find selector\")) {\n        // selector missing: create selector then retry registration\n    }\n    throw e;\n}","preventionTips":["Register the selector before publishing discovery config from client SDKs.","Double-check pluginName, selectorName and namespaceId in client config match the dashboard values.","After namespace migration, re-sync client namespace settings.","If racy, retry registration with backoff on the client side."],"tags":["resource-not-found","discovery","registration-race"],"backgroundTag":"record-not-found","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}