apache/druid · warning
Could not determine DruidNode for DiscoveryDruidNode
Error message
Could not determine DruidNode for DiscoveryDruidNode[%s]
What it means
BaseDynamicConfigSyncer converts DiscoveryDruidNode entries (from the cluster view) into ServiceLocation objects for dynamic config sync. If a discovered node has no DruidNode attached, the converter logs this warning and returns null, meaning that node is excluded from sync targets (e.g. broker list). It signals a node advertised itself to the discovery/DruidNodeService without complete node data.
Solutions
- Inspect the offending node's registration (look at its logs/startup) so it registers with a valid DruidNode
- Check for extension or custom service-emitting code that constructs DiscoveryDruidNode without a DruidNode
- Restart the misbehaving node so it re-registers fully in the cluster view
Example fix
// before (extension code)
new DiscoveryDruidNode(null, NodeType.BROKER, null)
// after
new DiscoveryDruidNode(new DruidNode("broker", host, true, port, null, TLSMode.DISABLED, false), NodeType.BROKER, null) Defensive patterns
Strategy: type-guard
Validate before calling
if (discoveryNode.getDruidNode() == null) { skip; } Type guard
Optional<ServiceLocation> toLocation(DiscoveryDruidNode n) { return Optional.ofNullable(n).map(DiscoveryDruidNode::getDruidNode).filter(Objects::nonNull).map(d -> new ServiceLocation(d.getHost(), d.getPlaintextPort(), ...)); } Try / catch
try { ServiceLocation loc = syncer.brokerLocation(node); if (loc == null) { LOG.warn("Node {} has no DruidNode; excluding", node); } } catch (Exception e) { /* treat as unavailable */ } Prevention
- Ensure all services register complete DruidNode data at startup
- Audit extensions that create DiscoveryDruidNode instances
- Handle null ServiceLocation in sync callers defensively
When it happens
Trigger: brokerLocation() (or syncer refresh) encounters a DiscoveryDruidNode whose getDruidNode() is null — e.g. a node registered an empty/partial DiscoveryDruidNode in the service inventory, or a node type that does not carry a DruidNode.
Common situations: Partially started or misconfigured service announcing itself; custom node types/extensions emitting DiscoveryDruidNode without the inner node; transient cluster-view inconsistencies.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Action [ ] failed for worker [ ] with status ( )
- An external HTTP table with a URI must also provide the…
- An external HTTP table with a URI must also provide the…
- AuthenticationToken ignored:
- <authResult.getErrorMessage()>
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/acc83876912912a7.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/main/java/org/apache/druid/server/http/BaseDynamicConfigSyncer.java:261
/**
* Adds a broker to the set of inSyncBrokers if the dynamic config has not changed.
*/
private synchronized void markBrokerAsSynced(DynamicConfig config, ServiceLocation broker)
{
if (config.equals(lastKnownConfig.get())) {
inSyncBrokers.add(new BrokerSyncStatus(broker, System.currentTimeMillis()));
}
}
/**
* Utility method to convert {@link DiscoveryDruidNode} to a {@link ServiceLocation}
*/
@Nullable
private static ServiceLocation convertDiscoveryNodeToServiceLocation(DiscoveryDruidNode discoveryDruidNode)
{
final DruidNode druidNode = discoveryDruidNode.getDruidNode();
if (druidNode == null) {
log.warn("Could not determine DruidNode for DiscoveryDruidNode[%s]", discoveryDruidNode);
return null;
}
return new ServiceLocation(
druidNode.getHost(),
druidNode.getPlaintextPort(),
druidNode.getTlsPort(),
""
);
}
private void emitStat(CoordinatorStat stat, RowKey rowKey, long value)
{
ServiceMetricEvent.Builder eventBuilder = new ServiceMetricEvent.Builder();
rowKey.getValues().forEach(
(dim, dimValue) -> eventBuilder.setDimension(dim.reportedName(), dimValue)
);
emitter.emit(eventBuilder.setMetric(stat.getMetricName(), value));View on GitHub (pinned to 9b90983fd2)