apache/shenyu · warning · ShenyuException

doHeartbeat Failed to execute,wait to retry.

Error message

doHeartbeat Failed to execute,wait to retry.

What it means

doHeartbeat() throws ShenyuException when no SelectorDO exists for selectorName + pluginName + namespaceId, meaning a heartbeat arrived for a selector the admin does not know. Like doRegisterURI, the 'wait to retry' wording indicates an expected eventual-consistency race: heartbeats are usually retried by the client until the selector appears.

Solutions

  1. Let the client retry — Shenyu client registration retries heartbeats until the selector exists.
  2. Ensure metadata registration (selector creation) succeeds before/independent of heartbeat scheduling.
  3. Recreate the selector in the dashboard if it was deleted intentionally while the service is still up.
  4. Check namespaceId consistency between the client config and the selector's namespace.
Defensive patterns

Strategy: retry

Validate before calling

SelectorDO selector = selectorService.findByNameAndPluginNameAndNamespaceId(selectorName, pluginName, namespaceId);
if (selector == null) {
    // delay heartbeat until metadata registration has created the selector
    return;
}

Try / catch

try {
    registerService.doHeartbeat(selectorName, uriList, namespaceId);
} catch (ShenyuException e) {
    if (e.getMessage().contains("doHeartbeat Failed")) {
        scheduler.schedule(() -> doHeartbeatWithRetry(selectorName, uriList, namespaceId), 5, SECONDS);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Client sends periodic heartbeats for a selectorName that is absent in the DB for that namespace/plugin — heartbeat scheduled before the initial metadata/selector registration completed, or selector deleted in the dashboard while the client is still running.

Common situations: Client restarted before admin registered its metadata; heartbeat timer faster than registration; namespaceId mismatch; an operator removed the selector but left the backend service running and heartbeating.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java:247

        PluginDO pluginDO = pluginMapper.selectByName(pluginName);
        if (Objects.isNull(pluginDO)) {
            throw new IllegalArgumentException(errorMsg);
        }
        NamespacePluginVO namespacePluginRelation = namespacePluginRelMapper.selectByPluginIdAndNamespaceId(pluginDO.getId(), namespaceId);
        if (Objects.isNull(namespacePluginRelation)) {
            throw new IllegalArgumentException(errorMsg);
        }
    }
    
    @Override
    public String doHeartbeat(final String selectorName, final List<URIRegisterDTO> uriList, final String namespaceId) {
        if (CollectionUtils.isEmpty(uriList)) {
            return "";
        }
        String pluginName = PluginNameAdapter.rpcTypeAdapter(rpcType());
        SelectorDO selectorDO = selectorService.findByNameAndPluginNameAndNamespaceId(selectorName, pluginName, namespaceId);
        if (Objects.isNull(selectorDO)) {
            throw new ShenyuException("doHeartbeat Failed to execute,wait to retry.");
        }
        // update upstream
        List<URIRegisterDTO> validUriList = uriList.stream().filter(dto -> Objects.nonNull(dto.getPort()) && StringUtils.isNotBlank(dto.getHost())).toList();
        if (CollectionUtils.isEmpty(validUriList)) {
            return null;
        }
        // discovery publish change event.
        String selectorId = selectorDO.getId();
        // change live node status to TRUE
        validUriList.forEach(uriRegisterDTO -> {
            DiscoveryUpstreamDTO discoveryUpstreamDTO = CommonUpstreamUtils.buildDefaultDiscoveryUpstreamDTO(uriRegisterDTO.getHost(),
                    uriRegisterDTO.getPort(),
                    uriRegisterDTO.getProtocol(),
                    uriRegisterDTO.getNamespaceId());

            try {
                // publish instance info event
                InstanceInfoReportEvent instanceInfoReportEvent = new InstanceInfoReportEvent(

View on GitHub (pinned to 567142e072)