pentaho/pentaho-kettle · error · KettleXMLException
RulesMeta.Error.LoadFromXML
RulesMeta.Error.LoadFromXML
Error message
RulesMeta.Error.LoadFromXML
What it means
RulesExecutorMeta.loadXML() deserializes the Rules Executor step configuration from the transformation's .ktr XML: it reads the <fields> result-column entries (creating a ValueMetaInterface per field via ValueMetaFactory.createValueMeta) and the rule-file / rule-definition tags. Any exception in this block is wrapped in a KettleXMLException with the i18n message "RulesMeta.Error.LoadFromXML", meaning the persisted step definition could not be loaded.
Solutions
- Inspect the KettleXMLException's cause (getCause()) to find the underlying failure (usually the unmapped value-type name or an NPE).
- Open the .ktr in a text editor and validate each <field>'s column-name/column-type inside the step's <fields> block against valid PDI value types.
- Delete and re-add the Rules Executor step in Spoon, reconfigure, and re-save to regenerate clean XML.
- Restore the transformation from backup or version control if the file is corrupted/truncated.
- If upgrading PDI, use the documented migration path rather than reusing old XML directly.
Example fix
<!-- before: missing <fields> wrapper breaks loadXML -->
<field>
<column-name>result</column-name>
<column-type>String</column-type>
</field>
<!-- after -->
<fields>
<field>
<column-name>result</column-name>
<column-type>String</column-type>
</field>
</fields> Defensive patterns
Strategy: try-catch
Validate before calling
// Before loading from XML, check required structure and types
Node fields = XMLHandler.getSubNode(stepnode, "fields");
if (fields == null) throw new IllegalArgumentException("Rules Executor XML missing <fields> node");
for (int i = 0; i < XMLHandler.countNodes(fields, "field"); i++) {
Node f = XMLHandler.getSubNodeByNr(fields, "field", i);
String type = XMLHandler.getTagValue(f, "column-type");
if (type == null || ValueMeta.getType(type) < 0)
throw new IllegalArgumentException("invalid column-type: " + type);
} Type guard
boolean isLoadableRulesExecutorNode(Node stepnode) {
Node fields = XMLHandler.getSubNode(stepnode, "fields");
if (fields == null) return false;
int n = XMLHandler.countNodes(fields, "field");
for (int i = 0; i < n; i++) {
String type = XMLHandler.getTagValue(XMLHandler.getSubNodeByNr(fields, "field", i), "column-type");
if (type == null || ValueMeta.getType(type) < 0) return false;
}
return true;
} Try / catch
try {
meta.loadXML(stepnode, databases, metaStore);
} catch (KettleXMLException e) {
logError("Rules Executor step XML failed to load: " + e.getCause(), e);
throw new KettleXMLException("Invalid Rules Executor XML — verify <fields> block and column-type values", e);
} Prevention
- Configure the step via Spoon rather than editing XML by hand
- Validate column-type names against PDI ValueMeta type descriptions
- Back up .ktr files in version control to restore from corruption
- After PDI upgrades, reopen and re-save transformations to normalize step XML
When it happens
Trigger: Loading a Rules Executor step from XML when the <fields>/<field> structure is malformed or missing (NPE in getSubNode/countNodes), a column-type value that ValueMeta.getType()/ValueMetaFactory cannot resolve, createValueMeta throwing for an unsupported type code, or XMLHandler failing while reading rule-file/rule-definition tags.
Common situations: Transformation saved by a different PDI version with a changed XML schema; hand-edited .ktr with an invalid column-type name; corrupted/truncated transformation file; XML copied between transformations with missing nodes.
Related errors
- RulesMeta.Error.LoadFromXML
- AbortMeta.Exception.UnexpectedErrorInReadingStepInfoFromRepo…
- AggregateRowsMeta.Exception.UnableToLoadStepInfo
- CubeOutputMeta.Exception.UnableToLoadStepInfo
- DelayMeta.Exception.UnableToReadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/e0bfc81dbc932e9c.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/drools/core/src/main/java/org/pentaho/di/trans/steps/rules/RulesExecutorMeta.java:153
try {
Node fields = XMLHandler.getSubNode( stepnode, StorageKeys.NODE_FIELDS.toString() );
int nrfields = XMLHandler.countNodes( fields, StorageKeys.SUBNODE_FIELD.toString() );
ValueMetaInterface vm = null;
for ( int i = 0; i < nrfields; i++ ) {
Node fnode = XMLHandler.getSubNodeByNr( fields, StorageKeys.SUBNODE_FIELD.toString(), i );
String name = XMLHandler.getTagValue( fnode, StorageKeys.COLUMN_NAME.toString() );
int type = ValueMeta.getType( XMLHandler.getTagValue( fnode, StorageKeys.COLUMN_TYPE.toString() ) );
vm = ValueMetaFactory.createValueMeta( name, type );
getRuleResultColumns().add( vm );
}
setRuleFile( XMLHandler.getTagValue( stepnode, StorageKeys.RULE_FILE.toString() ) );
setRuleDefinition( XMLHandler.getTagValue( stepnode, StorageKeys.RULE_DEFINITION.toString() ) );
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "RulesMeta.Error.LoadFromXML" ), e );
}
}
@Override
public String getXML() {
StringBuffer retval = new StringBuffer( 300 );
retval.append( " <" + StorageKeys.NODE_FIELDS + ">" ).append( Const.CR );
for ( int i = 0; i < ruleResultColumns.size(); i++ ) {
retval.append( " <" + StorageKeys.SUBNODE_FIELD + ">" ).append( Const.CR );
retval.append( " " ).append(
XMLHandler.addTagValue( StorageKeys.COLUMN_NAME.toString(), ruleResultColumns.get( i ).getName() ) );
retval.append( " " ).append(
XMLHandler.addTagValue( StorageKeys.COLUMN_TYPE.toString(), ruleResultColumns.get( i ).getTypeDesc() ) );
retval.append( " </" + StorageKeys.SUBNODE_FIELD + ">" ).append( Const.CR );
}
retval.append( " </" + StorageKeys.NODE_FIELDS + ">" ).append( Const.CR );
retval.append( " " ).append( XMLHandler.addTagValue( StorageKeys.RULE_FILE.toString(), getRuleFile() ) );View on GitHub (pinned to f3058517a1)