pentaho/pentaho-kettle · error · KettleXMLException

Unable to load step info from XML

Error message

Unable to load step info from XML

What it means

S3CsvInputMeta.readData parses the step's XML definition (fields, delimiter, encoding, etc.) when a transformation is loaded. Any exception while reading XML tags is wrapped in a KettleXMLException 'Unable to load step info from XML'.

Solutions

  1. Open the .ktr in Spoon and re-save the S3 CSV Input step to regenerate valid XML
  2. Compare the step XML against a working transformation to find missing/renamed tags
  3. Read the wrapped cause to identify which tag failed
  4. Migrate the transformation through a compatible Pentaho version if schemas differ

Example fix

// before (broken ktr snippet)
<trim_type>non</trim_typ>
// after
<trim_type>none</trim_type>
Defensive patterns

Strategy: try-catch

Validate before calling

if ( stepnode == null || XMLHandler.getTagValue( stepnode, "fields" ) == null ) {
  throw new IllegalArgumentException( "missing S3CsvInput XML node" );
}

Try / catch

try {
  loadXML( stepnode, databases, metaStore );
} catch ( KettleXMLException e ) {
  logError( "Corrupt S3 CSV Input XML: " + e.getCause() );
  throw e;
}

Prevention

When it happens

Trigger: Loading a .ktr whose S3 CSV Input XML node is malformed or missing expected tags (fields, trim_type, format, etc.) — XMLHandler.getTagValue or field parsing throws.

Common situations: Hand-edited or truncated .ktr files; transformation produced by a newer/older Pentaho version with a changed XML schema; corrupted export; copy-paste of step XML with wrong node structure.

Related errors


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

Appendix: source

Thrown at plugins/s3csvinput/core/src/main/java/org/pentaho/di/trans/steps/s3csvinput/S3CsvInputMeta.java:186

      allocate( nrfields );

      for ( int i = 0; i < nrfields; i++ ) {
        inputFields[i] = new TextFileInputField();

        Node fnode = XMLHandler.getSubNodeByNr( fields, "field", i );

        inputFields[i].setName( XMLHandler.getTagValue( fnode, "name" ) );
        inputFields[i].setType( ValueMetaFactory.getIdForValueMeta( XMLHandler.getTagValue( fnode, "type" ) ) );
        inputFields[i].setFormat( XMLHandler.getTagValue( fnode, "format" ) );
        inputFields[i].setCurrencySymbol( XMLHandler.getTagValue( fnode, "currency" ) );
        inputFields[i].setDecimalSymbol( XMLHandler.getTagValue( fnode, "decimal" ) );
        inputFields[i].setGroupSymbol( XMLHandler.getTagValue( fnode, "group" ) );
        inputFields[i].setLength( Const.toInt( XMLHandler.getTagValue( fnode, "length" ), -1 ) );
        inputFields[i].setPrecision( Const.toInt( XMLHandler.getTagValue( fnode, "precision" ), -1 ) );
        inputFields[i].setTrimType( ValueMetaString.getTrimTypeByCode( XMLHandler.getTagValue( fnode, "trim_type" ) ) );
      }
    } catch ( Exception e ) {
      throw new KettleXMLException( "Unable to load step info from XML", e );
    }
  }

  public void allocate( int nrFields ) {
    inputFields = new TextFileInputField[nrFields];
  }

  @Override
  public String getXML() {
    StringBuffer retval = new StringBuffer( 500 );

    retval.append( "    " ).append( XMLHandler.addTagValue( "aws_access_key", Encr.encryptPasswordIfNotUsingVariables(
        awsAccessKey ) ) );
    retval.append( "    " ).append( XMLHandler.addTagValue( "aws_secret_key", Encr.encryptPasswordIfNotUsingVariables(
        awsSecretKey ) ) );
    retval.append( "    " ).append( XMLHandler.addTagValue( "bucket", bucket ) );
    retval.append( "    " ).append( XMLHandler.addTagValue( "filename", filename ) );
    retval.append( "    " ).append( XMLHandler.addTagValue( "filename_field", filenameField ) );

View on GitHub (pinned to f3058517a1)