elastic/elasticsearch · error · IllegalArgumentException
Cannot shrink {} to have {} nodes as it already has {}
Error message
Cannot shrink {} to have {} nodes as it already has {} What it means
Thrown by ElasticsearchCluster.setNumberOfNodes when the requested count is smaller than the number of nodes already in the cluster. The list only grows (new ElasticsearchNode entries are appended in the loop below); shrinking is not supported because removing running nodes from a test cluster is unsafe.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchCluster.java:177
public FileCollection getInstalledClasspath() {
return pluginAndModuleConfiguration.getAsFileTree().filter(f -> f.getName().endsWith(".jar"));
}
@InputFiles
@PathSensitive(PathSensitivity.RELATIVE)
public FileCollection getInstalledFiles() {
return pluginAndModuleConfiguration.getAsFileTree().filter(f -> f.getName().endsWith(".jar") == false);
}
public void setNumberOfNodes(int numberOfNodes) {
checkFrozen();
if (numberOfNodes < 1) {
throw new IllegalArgumentException("Number of nodes should be >= 1 but was " + numberOfNodes + " for " + this);
}
if (numberOfNodes < nodes.size()) {
throw new IllegalArgumentException(
"Cannot shrink " + this + " to have " + numberOfNodes + " nodes as it already has " + getNumberOfNodes()
);
}
for (int i = nodes.size(); i < numberOfNodes; i++) {
this.nodes.add(
new ElasticsearchNode(
safeName(clusterName),
path,
clusterName + "-" + i,
project,
reaper,
testClustersRegistryProvider,
fileSystemOperations,
archiveOperations,
execOperations,
fileOperations,
workingDirBase,View on GitHub (pinned to db6a809a66)
Solutions
- Only ever increase numberOfNodes for a given cluster instance; declare separate testClusters blocks if different sizes are needed.
- Audit ordering of setNumberOfNodes calls — move the largest required size to the earliest point.
- If a smaller cluster is genuinely needed, define a distinct testCluster (e.g. testClusters { small {} }) rather than reusing one.
Example fix
// before
testClusters {
numberOfNodes = 3
}
tasks.named('integTest').configure {
// later, in a different task reusing the same cluster
doFirst { testClusters.cluster.numberOfNodes = 1 } // throws
}
// after
testClusters {
big { numberOfNodes = 3 }
small { numberOfNodes = 1 }
}
tasks.named('integTestBig').configure { useCluster testClusters.big }
tasks.named('integTestSmall').configure { useCluster testClusters.small } Defensive patterns
Strategy: validation
Validate before calling
int current = cluster.getNumberOfNodes();
if (requested < current) {
throw new IllegalStateException("Refusing to shrink cluster " + current + " -> " + requested);
}
cluster.setNumberOfNodes(requested); Prevention
- Treat numberOfNodes as monotonically increasing per cluster instance.
- Use distinct testClusters blocks for distinct sizes.
- Centralize the largest required size and set it once.
When it happens
Trigger: A cluster already has N nodes (added via prior setNumberOfNodes or node {} blocks) and a later setNumberOfNodes(M) call has M < N.
Common situations: Two test tasks share a cluster spec but request different sizes; a setup hook sets a higher count then a per-test override tries to lower it; dynamic resizing based on a parameter that decreased between runs.
Related errors
- Number of nodes should be >= 1 but was {} for {}
- Cannot add nodes to test cluster after is has been frozen
- Configuration for {} can not be altered, already locked
- Ran out of nodes to take to the next version
- Can't treat {} as single node as it has {} nodes
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/100e3569113878ba.
Report an issue: GitHub.