{"record":{"id":"b57f9317792dedab","repo":"apache/dolphinscheduler","slug":"failed-to-subscribe-listener-for-key","errorCode":null,"errorMessage":"Failed to subscribe listener for key: ","messagePattern":"Failed to subscribe listener for key: ","errorType":"exception","errorClass":"RegistryException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-zookeeper/src/main/java/org/apache/dolphinscheduler/plugin/registry/zookeeper/ZookeeperRegistry.java","lineNumber":149,"sourceCode":"            }\n        } catch (RegistryException e) {\n            throw e;\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw new RegistryException(\n                    String.format(\"Cannot connect to registry in %s s\", timeout.getSeconds()), e);\n        }\n    }\n\n    @Override\n    public void subscribe(final String path, final SubscribeListener listener) {\n        final TreeCache treeCache = treeCacheMap.computeIfAbsent(path, $ -> new TreeCache(client, path));\n        treeCache.getListenable().addListener(new ZookeeperTreeCacheListenerAdapter(path, listener));\n        try {\n            treeCache.start();\n        } catch (Exception e) {\n            treeCacheMap.remove(path);\n            throw new RegistryException(\"Failed to subscribe listener for key: \" + path, e);\n        }\n    }\n\n    @Override\n    public String get(String key) {\n        try {\n            return new String(client.getData().forPath(key), StandardCharsets.UTF_8);\n        } catch (Exception e) {\n            throw new RegistryException(\"zookeeper get data error\", e);\n        }\n    }\n\n    @Override\n    public boolean exists(String key) {\n        try {\n            return null != client.checkExists().forPath(key);\n        } catch (Exception e) {\n            throw new RegistryException(\"zookeeper check key is existed error\", e);","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-registry/dolphinscheduler-registry-plugins/dolphinscheduler-registry-zookeeper/src/main/java/org/apache/dolphinscheduler/plugin/registry/zookeeper/ZookeeperRegistry.java#L131-L167","documentation":"ZookeeperRegistry.subscribe() wraps any failure while starting a Curator TreeCache for the subscribed path in a RegistryException. The TreeCache is created, the listener adapter is attached, and treeCache.start() performs an initial sync of the subtree from the ZooKeeper server; if that sync or setup fails, the cache entry is rolled back out of treeCacheMap and this error is thrown.","triggerScenarios":"Calling subscribe(key, listener) when the ZooKeeper session is down or expired, when the client cannot reach the ensemble (connect timeout), when authentication/ACLs deny reading the path, or when the path contains invalid characters (e.g. empty key or key with null bytes) causing TreeCache.start() to fail.","commonSituations":"ZooKeeper ensemble unreachable after network partition or misquoted connect string (e.g. wrong port in registry.zookeeper.connect-string); session expired due to long GC pause; SASL/ACL misconfiguration after tightening server permissions; subscribing to a malformed key built from a null/empty task parameter.","solutions":["Verify ZooKeeper connectivity with `echo ruok | nc <host> 2181` and check registry.zookeeper.connect-string, auth and session-timeout settings in dolphinscheduler-common config","Check server ACLs/ZooKeeper authorization config so the client user can read the subscribed path","Ensure the subscribed key is a valid absolute ZNode path (starts with '/', no empty segments or null characters)","Retry the subscribe after the session recovers — Curator will re-establish the session; restart the master/worker if the client is stuck in a dead session","Inspect the wrapped cause `e` in the RegistryException — KeeperException codes (CONNECTIONLOSS, SESSIONEXPIRED, AUTHFAILED, BADARGUMENTS) pinpoint the root cause"],"exampleFix":"// before\nregistry.subscribe(\"/nodes/\" + nullHost, listener);\n// after\nString path = \"/nodes/\" + host;\nif (host == null || host.isEmpty()) { throw new IllegalArgumentException(\"host required\"); }\nregistry.subscribe(path, listener);","handlingStrategy":"try-catch","validationCode":"// validate path before subscribing\nif (key == null || !key.startsWith(\"/\") || key.contains(\"//\")) {\n    throw new IllegalArgumentException(\"invalid registry key: \" + key);\n}\nif (!isZkReachable(zkQuorum)) { /* check before subscribe */ }","typeGuard":null,"tryCatchPattern":"try {\n    registry.subscribe(key, listener);\n} catch (RegistryException e) {\n    logger.error(\"subscribe failed for {}: {}\", key, e.getCause() == null ? e : e.getCause().getMessage(), e);\n    if (e.getCause() instanceof KeeperException.ConnectionLossException || e.getCause() instanceof KeeperException.SessionExpiredException) {\n        scheduleRetrySubscribe(key, listener); // retry after session recovery\n    }\n}","preventionTips":["Keep ZooKeeper session timeouts sized above worst-case GC pauses","Monitor ensemble health (ruok/mntr four-letter words) before application startup","Validate key paths built from dynamic IDs before calling the registry","Use consistent registry.zookeeper.connect-string and auth config across all DolphinScheduler components"],"tags":["zookeeper","curator","registry","treecache"],"backgroundTag":"connection-refused","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}