pentaho/pentaho-kettle · error · KettleXMLException

Error loading transformation step from XML

Error message

Error loading transformation step from XML

What it means

SimpleMappingMeta.loadXML wraps the whole XML deserialization of the step in a try/catch; any exception while reading mappings, input/output MappingIODefinition entries, or MappingParameters is rethrown as a KettleXMLException with the message 'Error loading transformation step from XML' and the original cause attached.

Solutions

  1. Look at the chained cause (e.getCause()) in the stack trace to find the exact parse failure.
  2. Open the .ktr in an XML editor/linter and validate well-formedness and the expected <mappings> structure.
  3. Restore the step or file from a previous saved version / repository history.
  4. Rebuild the Simple Mapping step in Spoon and save a fresh copy of the transformation.
  5. Align Pentaho Data Integration versions between the writer and reader of the file.

Example fix

// Malformed parameter block
<mapping_parameters><parameter><name>p1</name></mapping_parameters>
// after - properly closed
<mapping_parameters><parameter><name>p1</name><value>1</value></parameter></mapping_parameters>
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate XML well-formedness and required nodes before loading
Document doc = XMLHandler.loadXMLFile(file);
if (doc == null) throw new IllegalStateException("XML is not well-formed: " + file);

Try / catch

try {
  transMeta.loadXML(fileName, null, metaStore, variables, false, null);
} catch (KettleXMLException e) {
  Throwable root = e; while (root.getCause() != null) root = root.getCause();
  logError("Error loading step XML, root cause: " + root.getMessage(), e);
}

Prevention

When it happens

Trigger: Any Exception thrown inside loadXML while parsing the <mappings> node, its <input>/<output> children (MappingIODefinition.XML_TAG) or the <mapping_parameters> (MappingParameters.XML_TAG) node - typically malformed or unexpected XML structure.

Common situations: Truncated .ktr files (incomplete save or disk issue); XML edited by hand with wrong tag names or nesting; version skew where an older engine reads XML written by a newer version with extra/renamed elements; corrupted content pulled from a repository.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/simplemapping/SimpleMappingMeta.java:162

        inputMapping = new MappingIODefinition( mappingNode );
      } else {
        inputMapping = new MappingIODefinition(); // empty
      }
      Node outputNode = XMLHandler.getSubNode( mappingsNode, "output" );
      mappingNode = XMLHandler.getSubNode( outputNode, MappingIODefinition.XML_TAG );
      if ( mappingNode != null ) {
        outputMapping = new MappingIODefinition( mappingNode );
      } else {
        outputMapping = new MappingIODefinition(); // empty
      }

      // Load the mapping parameters too..
      //
      Node mappingParametersNode = XMLHandler.getSubNode( mappingsNode, MappingParameters.XML_TAG );
      mappingParameters = new MappingParameters( mappingParametersNode );

    } catch ( Exception e ) {
      throw new KettleXMLException( BaseMessages.getString(
        PKG, "SimpleMappingMeta.Exception.ErrorLoadingTransformationStepFromXML" ), e );
    }
  }

  public Object clone() {
    Object retval = super.clone();
    return retval;
  }

  public String getXML() {
    StringBuilder retval = new StringBuilder( 300 );

    retval.append( "    " ).append(
      XMLHandler.addTagValue( "specification_method", specificationMethod == null ? null : specificationMethod
        .getCode() ) );
    retval.append( "    " ).append(
      XMLHandler.addTagValue( "trans_object_id", transObjectId == null ? null : transObjectId.toString() ) );
    // Export a little bit of extra information regarding the reference since it doesn't really matter outside the same

View on GitHub (pinned to f3058517a1)