elastic/elasticsearch · error · IllegalStateException
Can't treat {} as single node as it has {} nodes
Error message
Can't treat {} as single node as it has {} nodes What it means
Thrown by ElasticsearchCluster.singleNode() when the cluster does not have exactly one node. singleNode() returns the sole ElasticsearchNode for single-node convenience APIs; calling it on a multi-node (or zero-node) cluster is ambiguous and rejected.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java:638
@Internal
public List<String> getLeakMessages() {
return nodes.stream().map(ElasticsearchNode::getLeakMessage).filter(Objects::nonNull).toList();
}
@Override
public void setNameCustomization(Function<String, String> nameCustomization) {
nodes.all(each -> each.setNameCustomization(nameCustomization));
}
@Override
@Internal
public boolean isProcessAlive() {
return nodes.stream().noneMatch(node -> node.isProcessAlive() == false);
}
public ElasticsearchNode singleNode() {
if (nodes.size() != 1) {
throw new IllegalStateException("Can't treat " + this + " as single node as it has " + nodes.size() + " nodes");
}
return getFirstNode();
}
private void addWaitForClusterHealth() {
waitConditions.put("cluster health yellow", (node) -> {
try {
boolean httpSslEnabled = getFirstNode().isHttpSslEnabled();
WaitForHttpResource wait = new WaitForHttpResource(
httpSslEnabled ? "https" : "http",
getFirstNode().getHttpSocketURI(),
nodes.size()
);
if (httpSslEnabled) {
getFirstNode().configureHttpWait(wait);
}
List<Map<String, String>> credentials = getFirstNode().getCredentials();
if (getFirstNode().getCredentials().isEmpty() == false) {View on GitHub (pinned to db6a809a66)
Solutions
- Ensure the cluster is configured with numberOfNodes = 1 before calling singleNode().
- If multi-node, iterate getNodes() instead of calling singleNode().
- Add a guard at test entry: assumeTrue(cluster.getNodes().size() == 1) when the test requires single-node semantics.
Example fix
// before
testClusters { cluster { numberOfNodes = 3 } }
ElasticsearchNode n = testClusters.cluster.singleNode(); // throws
// after (single-node)
testClusters { cluster { numberOfNodes = 1 } }
ElasticsearchNode n = testClusters.cluster.singleNode();
// after (multi-node)
testClusters.cluster.getNodes().forEach(n -> { ... }); Defensive patterns
Strategy: validation
Validate before calling
if (cluster.getNodes().size() != 1) {
throw new IllegalStateException("singleNode() requires exactly 1 node, has " + cluster.getNodes().size());
}
ElasticsearchNode n = cluster.singleNode(); Prevention
- Reserve singleNode() for numberOfNodes = 1 clusters.
- Iterate getNodes() for multi-node clusters.
- Add assumeTrue(cluster.getNodes().size() == 1) in single-node test helpers.
When it happens
Trigger: Calling cluster.singleNode() when nodes.size() != 1 — either before any nodes are added, or after configuring a multi-node cluster.
Common situations: A test helper assumes a single-node cluster but the test cluster was configured with numberOfNodes > 1, or singleNode() is called early before node sizing has completed.
Related errors
- Number of nodes should be >= 1 but was {} for {}
- Cannot shrink {} to have {} nodes as it already has {}
- Ran out of nodes to take to the next version
- Not Supported API
- Testclusters does not allow the following settings to be cha
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/f59c68c54d21919e.
Report an issue: GitHub.