{"record":{"id":"e0bfc81dbc932e9c","repo":"pentaho/pentaho-kettle","slug":"rulesmeta-error-loadfromxml-e0bfc8","errorCode":"RulesMeta.Error.LoadFromXML","errorMessage":"RulesMeta.Error.LoadFromXML","messagePattern":"RulesMeta\\.Error\\.LoadFromXML","errorType":"exception","errorClass":"KettleXMLException","httpStatus":null,"severity":"error","filePath":"plugins/drools/core/src/main/java/org/pentaho/di/trans/steps/rules/RulesExecutorMeta.java","lineNumber":153,"sourceCode":"    try {\n      Node fields = XMLHandler.getSubNode( stepnode, StorageKeys.NODE_FIELDS.toString() );\n      int nrfields = XMLHandler.countNodes( fields, StorageKeys.SUBNODE_FIELD.toString() );\n\n      ValueMetaInterface vm = null;\n      for ( int i = 0; i < nrfields; i++ ) {\n        Node fnode = XMLHandler.getSubNodeByNr( fields, StorageKeys.SUBNODE_FIELD.toString(), i );\n\n        String name = XMLHandler.getTagValue( fnode, StorageKeys.COLUMN_NAME.toString() );\n        int type = ValueMeta.getType( XMLHandler.getTagValue( fnode, StorageKeys.COLUMN_TYPE.toString() ) );\n\n        vm = ValueMetaFactory.createValueMeta( name, type );\n        getRuleResultColumns().add( vm );\n      }\n\n      setRuleFile( XMLHandler.getTagValue( stepnode, StorageKeys.RULE_FILE.toString() ) );\n      setRuleDefinition( XMLHandler.getTagValue( stepnode, StorageKeys.RULE_DEFINITION.toString() ) );\n    } catch ( Exception e ) {\n      throw new KettleXMLException( BaseMessages.getString( PKG, \"RulesMeta.Error.LoadFromXML\" ), e );\n    }\n  }\n\n  @Override\n  public String getXML() {\n    StringBuffer retval = new StringBuffer( 300 );\n\n    retval.append( \"    <\" + StorageKeys.NODE_FIELDS + \">\" ).append( Const.CR );\n    for ( int i = 0; i < ruleResultColumns.size(); i++ ) {\n      retval.append( \"      <\" + StorageKeys.SUBNODE_FIELD + \">\" ).append( Const.CR );\n      retval.append( \"        \" ).append(\n        XMLHandler.addTagValue( StorageKeys.COLUMN_NAME.toString(), ruleResultColumns.get( i ).getName() ) );\n      retval.append( \"        \" ).append(\n        XMLHandler.addTagValue( StorageKeys.COLUMN_TYPE.toString(), ruleResultColumns.get( i ).getTypeDesc() ) );\n      retval.append( \"      </\" + StorageKeys.SUBNODE_FIELD + \">\" ).append( Const.CR );\n    }\n    retval.append( \"    </\" + StorageKeys.NODE_FIELDS + \">\" ).append( Const.CR );\n    retval.append( \"    \" ).append( XMLHandler.addTagValue( StorageKeys.RULE_FILE.toString(), getRuleFile() ) );","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/drools/core/src/main/java/org/pentaho/di/trans/steps/rules/RulesExecutorMeta.java#L135-L171","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"<!-- before: missing <fields> wrapper breaks loadXML -->\n<field>\n  <column-name>result</column-name>\n  <column-type>String</column-type>\n</field>\n\n<!-- after -->\n<fields>\n  <field>\n    <column-name>result</column-name>\n    <column-type>String</column-type>\n  </field>\n</fields>","handlingStrategy":"try-catch","validationCode":"// Before loading from XML, check required structure and types\nNode fields = XMLHandler.getSubNode(stepnode, \"fields\");\nif (fields == null) throw new IllegalArgumentException(\"Rules Executor XML missing <fields> node\");\nfor (int i = 0; i < XMLHandler.countNodes(fields, \"field\"); i++) {\n  Node f = XMLHandler.getSubNodeByNr(fields, \"field\", i);\n  String type = XMLHandler.getTagValue(f, \"column-type\");\n  if (type == null || ValueMeta.getType(type) < 0)\n    throw new IllegalArgumentException(\"invalid column-type: \" + type);\n}","typeGuard":"boolean isLoadableRulesExecutorNode(Node stepnode) {\n  Node fields = XMLHandler.getSubNode(stepnode, \"fields\");\n  if (fields == null) return false;\n  int n = XMLHandler.countNodes(fields, \"field\");\n  for (int i = 0; i < n; i++) {\n    String type = XMLHandler.getTagValue(XMLHandler.getSubNodeByNr(fields, \"field\", i), \"column-type\");\n    if (type == null || ValueMeta.getType(type) < 0) return false;\n  }\n  return true;\n}","tryCatchPattern":"try {\n  meta.loadXML(stepnode, databases, metaStore);\n} catch (KettleXMLException e) {\n  logError(\"Rules Executor step XML failed to load: \" + e.getCause(), e);\n  throw new KettleXMLException(\"Invalid Rules Executor XML — verify <fields> block and column-type values\", e);\n}","preventionTips":["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"],"tags":["kettle","xml","deserialization","step-metadata","transformation"],"backgroundTag":"xml-parse-error","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}