pentaho/pentaho-kettle · error · KettleXMLException

Unable to load step info from XML

Error message

Unable to load step info from XML

What it means

GetSubFoldersMeta.readData throws KettleXMLException 'Unable to load step info from XML' (with the cause) when deserializing the step from a .ktr fails while reading the folder/file nodes. Any exception in the XMLHandler calls (getNodes, getSubNodeByNr, getNodeValue) is wrapped, so a malformed or unexpected XML structure for this step surfaces as this error.

Solutions

  1. Validate and repair the step XML in the .ktr (each file node needs <name> and <file_required>).
  2. Re-create the Get SubFolders step in Spoon and re-save.
  3. Restore the transformation from backup/version control.
  4. Open the .ktr in a compatible PDI version matching the export's schema.

Example fix

// before: missing required sub-node
<file><name>/data</name></file>
// after
<file><name>/data</name><file_required>N</file_required></file>
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity-check the step node structure before loading
Node stepnode = XMLHandler.getSubNode( doc, "step" );
if ( XMLHandler.getNodeValue( XMLHandler.getSubNode( stepnode, "type" ) ) == null )
  throw new IllegalArgumentException( "Step XML missing <type> node" );

Try / catch

try {
  TransMeta tm = new TransMeta( ktrPath );
} catch ( KettleXMLException e ) {
  if ( e.getMessage().contains( "Unable to load step info from XML" ) ) {
    // inspect e.getCause(), repair/restore XML or recreate the step
  } else throw e;
}

Prevention

When it happens

Trigger: loadXML -> readData encounters an exception parsing <fields>/<folders> nodes, e.g. missing 'name' or 'file_required' sub-nodes, wrong node structure, or corrupt XML.

Common situations: Hand-edited or truncated .ktr files; older/newer PDI exports with different step XML schema; copy-paste of step XML from another transformation losing child nodes; encoding damage.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/getsubfolders/GetSubFoldersMeta.java:375

      rowNumberField = XMLHandler.getTagValue( stepnode, "rownum_field" );
      dynamicFoldernameField = XMLHandler.getTagValue( stepnode, "foldername_field" );

      // Is there a limit on the number of rows we process?
      rowLimit = Const.toLong( XMLHandler.getTagValue( stepnode, "limit" ), 0L );

      Node filenode = XMLHandler.getSubNode( stepnode, "file" );
      int nrfiles = XMLHandler.countNodes( filenode, "name" );

      allocate( nrfiles );

      for ( int i = 0; i < nrfiles; i++ ) {
        Node folderNamenode = XMLHandler.getSubNodeByNr( filenode, "name", i );
        Node folderRequirednode = XMLHandler.getSubNodeByNr( filenode, "file_required", i );
        folderName[i] = XMLHandler.getNodeValue( folderNamenode );
        folderRequired[i] = XMLHandler.getNodeValue( folderRequirednode );
      }
    } catch ( Exception e ) {
      throw new KettleXMLException( "Unable to load step info from XML", e );
    }
  }

  public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException {
    try {
      int nrfiles = rep.countNrStepAttributes( id_step, "file_name" );

      dynamicFoldernameField = rep.getStepAttributeString( id_step, "foldername_field" );

      includeRowNumber = rep.getStepAttributeBoolean( id_step, "rownum" );
      isFoldernameDynamic = rep.getStepAttributeBoolean( id_step, "foldername_dynamic" );
      rowNumberField = rep.getStepAttributeString( id_step, "rownum_field" );
      rowLimit = rep.getStepAttributeInteger( id_step, "limit" );

      allocate( nrfiles );

      for ( int i = 0; i < nrfiles; i++ ) {
        folderName[i] = rep.getStepAttributeString( id_step, i, "file_name" );

View on GitHub (pinned to f3058517a1)