pentaho/pentaho-kettle · error · KettleXMLException

RulesMeta.Error.LoadFromXML

RulesMeta.Error.LoadFromXML

Error message

RulesMeta.Error.LoadFromXML

What it means

RulesAccumulatorMeta.loadXML() deserializes the step's saved configuration from a .ktr XML document: it reads the <fields> node, creates a ValueMetaInterface per <field> child (via ValueMetaFactory.createValueMeta with the type parsed from column-type), and reads rule-file / rule-definition tags. Any exception in this block is wrapped in a KettleXMLException with the i18n message "RulesMeta.Error.LoadFromXML". It means the step definition stored in the transformation XML could not be loaded.

Solutions

  1. Inspect the 'cause' of the KettleXMLException (getCause()) — it contains the real error, e.g. the unmapped value-type name.
  2. Open the .ktr in a text editor and check the step's <fields>/<field> entries: verify each column-type is a valid PDI value type name (String, Integer, Number, Boolean, Date, ...).
  3. Recreate the step in Spoon and re-save if the XML is from an incompatible PDI version; migrate the transformation instead of hand-editing.
  4. Check for NPE caused by a missing <fields> node and add/repair the node structure.
  5. Ensure the transformation file is complete and not truncated/corrupted (re-export or restore from backup).

Example fix

<!-- before: invalid column type in the .ktr -->
<field>
  <column-name>total</column-name>
  <column-type>Intr</column-type>
</field>

<!-- after -->
<field>
  <column-name>total</column-name>
  <column-type>Integer</column-type>
</field>
Defensive patterns

Strategy: try-catch

Validate before calling

// Before loading from XML, validate the step node structure
Node fields = XMLHandler.getSubNode(stepnode, "fields");
if (fields == null) throw new IllegalArgumentException("step 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 (ValueMeta.getType(type) == ValueMetaInterface.TYPE_NONE)
    throw new IllegalArgumentException("unmapped column-type: " + type);
}

Type guard

boolean hasValidFieldsNode(Node stepnode) {
  Node fields = XMLHandler.getSubNode(stepnode, "fields");
  if (fields == null) return false;
  for (int i = 0; i < XMLHandler.countNodes(fields, "field"); 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("Failed to load Rule Accumulator step XML: " + e.getCause(), e);
  throw new KettleXMLException("Step XML invalid; check <fields> entries and column-type values", e);
}

Prevention

When it happens

Trigger: KettleXMLException thrown when loading a Rule Accumulator step from a transformation XML: malformed <fields> structure (e.g. fields node null leading to NPE in countNodes/getSubNodeByNr), a column-type string that ValueMeta.getType()/ValueMetaFactory cannot map to a value type, createValueMeta failing for an unsupported type, or XMLHandler throwing while parsing rule-file/rule-definition tags.

Common situations: Opening a .ktr file produced by a newer/older PDI version with changed step XML schema; hand-edited transformation XML with a typo in column-type (e.g. "Intr" instead of "Integer"); corrupted or partially written transformation file; XML missing the <fields> block entirely.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/6f9644968a356580. Report an issue: GitHub.

Appendix: source

Thrown at plugins/drools/core/src/main/java/org/pentaho/di/trans/steps/rules/RulesAccumulatorMeta.java:146

    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)