pentaho/pentaho-kettle · error · KettleXMLException
Unable to load step info from XML
Error message
Unable to load step info from XML
What it means
XMLInputStreamMeta.loadXML() parses step configuration from a transformation XML node using XMLHandler.getTagValue(). Any exception while reading those attributes is wrapped in a KettleXMLException with the message 'Unable to load step info from XML', with the underlying cause chained. This is a serialization/deserialization boundary error: the step definition stored in a .ktr file is unreadable or invalid.
Solutions
- Open the .ktr in a text editor and validate the XML well-formedness (e.g. xmllint --noout file.ktr); fix syntax errors.
- Check the chained cause exception (e.getCause()) to identify which element failed to parse.
- Recreate the XMLInputStream step in Spoon and re-enter its settings instead of editing XML manually.
- Verify the transformation was exported by a compatible PDI version; re-export or upgrade the PDI version.
- Restore the .ktr from source control or a backup if the file is corrupted.
Example fix
// before: hand-edited XML with a missing closing tag inside the step node <step name="XML Input" type="XMLInputStream"> <encoding>UTF-8 </step> // after: well-formed step node <step name="XML Input" type="XMLInputStream"> <encoding>UTF-8</encoding> </step>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the .ktr is well-formed before loading
Document doc = XMLHandler.loadXMLFile(new File("trans.ktr"));
if (doc == null) throw new IllegalArgumentException("Malformed transformation XML"); Type guard
boolean isReadableStepNode(Node stepnode) {
return stepnode != null && stepnode.getNodeType() == Node.ELEMENT_NODE
&& "step".equals(stepnode.getNodeName());
} Try / catch
try {
transMeta.loadXML(...);
} catch (KettleXMLException e) {
log.error("Step XML unreadable: {}", e.getCause(), e);
// fall back to backup .ktr or prompt user to re-create the step
} Prevention
- Never hand-edit .ktr files; use Spoon.
- Keep PDI client and repository/export versions aligned.
- Validate .ktr XML with a linter before committing or deploying.
- Keep transformation files in version control so corruption is recoverable.
When it happens
Trigger: Opening/validating a .ktr transformation whose XMLInputStream step XML node contains malformed XML, an unexpected node structure, or whose attribute parsing throws (e.g. XMLHandler.getTagValue fails on a malformed stepnode subtree). Also thrown when a transformation was written by an incompatible PDI version with an unreadable step entry.
Common situations: Hand-edited .ktr files with broken XML; transformations from newer PDI versions opened in older ones; corrupted repository exports; copying step XML between transformations with mismatched structure; encoding issues in the file.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- SampleRowsMeta.Exception.UnableToReadStepInfo
- Unable to load step info from XML
- ColumnExistsMeta.Exception.UnableToReadStepInfo
- CreditCardValidatorMeta.Exception.UnableToReadStepInfo
- CubeOutputMeta.Exception.UnableToLoadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/f85588ec153de865.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/xml/core/src/main/java/org/pentaho/di/trans/steps/xmlinputstream/XMLInputStreamMeta.java:301
"Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "includeXmlElementLevelField" ) );
xmlElementLevelField =
Const.NVL( XMLHandler.getTagValue( stepnode, "xmlElementLevelField" ), xmlElementLevelField );
includeXmlPathField = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "includeXmlPathField" ) );
xmlPathField = Const.NVL( XMLHandler.getTagValue( stepnode, "xmlPathField" ), xmlPathField );
includeXmlParentPathField =
"Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "includeXmlParentPathField" ) );
xmlParentPathField = Const.NVL( XMLHandler.getTagValue( stepnode, "xmlParentPathField" ), xmlParentPathField );
includeXmlDataNameField = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "includeXmlDataNameField" ) );
xmlDataNameField = Const.NVL( XMLHandler.getTagValue( stepnode, "xmlDataNameField" ), xmlDataNameField );
includeXmlDataValueField = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "includeXmlDataValueField" ) );
xmlDataValueField = Const.NVL( XMLHandler.getTagValue( stepnode, "xmlDataValueField" ), xmlDataValueField );
} catch ( Exception e ) {
throw new KettleXMLException( "Unable to load step info from XML", e );
}
}
@Override
public Object clone() {
XMLInputStreamMeta retval = (XMLInputStreamMeta) super.clone();
// TODO check
return retval;
}
@Override
public String getXML() {
StringBuffer retval = new StringBuffer();
retval.append( " " + XMLHandler.addTagValue( "sourceFromInput", sourceFromInput ) );
retval.append( " " + XMLHandler.addTagValue( "sourceFieldName", sourceFieldName ) );
retval.append( " " + XMLHandler.addTagValue( "filename", filename ) );
retval.append( " " + XMLHandler.addTagValue( "addResultFile", addResultFile ) );View on GitHub (pinned to f3058517a1)