pentaho/pentaho-kettle · error · KettleException
You always need at least one master in a cluster schema.
Error message
You always need at least one master in a cluster schema.
What it means
During the dynamic-cluster normalization in TransSplitter, if the cluster schema is dynamic its master is resolved via clusterSchema.findMaster(); when no slave server is flagged as master the splitter throws KettleException 'You always need at least one master in a cluster schema.' A dynamic cluster must be able to identify exactly which server will act as master.
Solutions
- Open the cluster schema in Spoon and mark one of its slave servers as master (checkbox 'is the master server').
- In code, set master on one slave: slaveServers.get(0).setMaster(true) before execution.
- Alternatively make the schema non-dynamic and explicitly list the master and slaves.
- Validate the SlaveServer metadata (hostname/port) so findMaster() can match the defined master.
Example fix
// before List<SlaveServer> slaves = ...; // none marked master ClusterSchema cs = new ClusterSchema(name, slaves, ...); cs.setDynamic(true); // after slaves.get(0).setMaster(true); ClusterSchema cs = new ClusterSchema(name, slaves, ...); cs.setDynamic(true);
Defensive patterns
Strategy: validation
Validate before calling
ClusterSchema cs = transMeta.findFirstUsedClusterSchema();
if (cs != null && cs.isDynamic() && cs.findMaster() == null) {
throw new IllegalStateException("Dynamic cluster schema '" + cs.getName() + "' has no master");
} Try / catch
try {
splitter.splitOriginalTransformation();
} catch (KettleException e) {
if (e.getMessage().contains("at least one master")) {
// mark a slave as master and retry
}
} Prevention
- Always tick the master checkbox on one slave server of a dynamic cluster
- Validate cluster schema metadata before submitting jobs
- Keep SlaveServer definitions consistent across environment imports
When it happens
Trigger: splitOriginalTransformation() on a transformation whose ClusterSchema.isDynamic() is true but whose slave server list contains no SlaveServer with isMaster()==true.
Common situations: Defining a dynamic cluster schema in Spoon without ticking 'Master' on any of its slave servers; deleting or demoting the master server in the cluster dialog; importing a cluster schema JSON missing master designation.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- At least one slave server is required to be present in…
- At this time we don't support the use of multiple cluster…
- ClusterSchema.NoMasterServerDefined
- ClusterSchema.NoSlaveServerDefined
- It doesn't make sense to have a partitioned, clustered step…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/3b5f4d3e83b425dd.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/cluster/TransSplitter.java:146
Repository rep = transMeta.getRepository();
if ( rep != null ) {
rep.readTransSharedObjects( this.originalTransformation );
}
checkClusterConfiguration();
// FIRST : convert the dynamic master into a fixed one.
// This is why we copied the original transformation
//
ClusterSchema clusterSchema = this.originalTransformation.findFirstUsedClusterSchema();
if ( clusterSchema == null ) {
throw new KettleException( "No clustering is used in this transformation." );
}
if ( clusterSchema.isDynamic() ) {
List<SlaveServer> slaveServers = clusterSchema.getSlaveServersFromMasterOrLocal();
SlaveServer masterSlaveServer = clusterSchema.findMaster();
if ( masterSlaveServer == null ) {
throw new KettleException( "You always need at least one master in a cluster schema." );
}
slaveServers.add( 0, masterSlaveServer );
clusterSchema.setDynamic( false );
clusterSchema.setSlaveServers( slaveServers );
}
}
/**
* @return the originalTransformation
*/
public TransMeta getOriginalTransformation() {
return originalTransformation;
}
/**
* @param originalTransformation
* the originalTransformation to set
*/View on GitHub (pinned to f3058517a1)