pentaho/pentaho-kettle · error · KettleXMLException
MergeJoinMeta.Exception.UnableToLoadStepInfo
MergeJoinMeta.Exception.UnableToLoadStepInfo
Error message
MergeJoinMeta.Exception.UnableToLoadStepInfo
What it means
Thrown by MergeJoinMeta.readData (called from loadXML) when parsing the step's XML node fails with any Exception. The step definition is loaded from a .ktr file; fields read are step1, step2 (input stream names) and join_type. The original exception is wrapped in a KettleXMLException.
Solutions
- Inspect the wrapped cause (KettleXMLException.getCause()) to find the exact XML parsing failure.
- Open the .ktr in Spoon and re-save the Merge Join step to regenerate well-formed XML for the node.
- Validate the XML file is well-formed (xmllint) and that <step1>, <step2>, <join_type> elements exist under the step node.
- Restore the transformation from version control or a backup if the file was hand-edited or merge-conflicted.
Example fix
// before (broken hand-edited XML) <join_type>INNER JOIM</join_type> // after <join_type>INNER</join_type>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the .ktr XML before loading
Document doc = XMLHandler.loadXMLFile(ktrFile);
if (XMLHandler.getSubNode(doc, "transformation") == null) {
throw new IllegalArgumentException("Not a valid transformation file");
} Try / catch
try {
TransMeta tm = new TransMeta(ktrFile);
} catch (KettleXMLException e) {
log.error("Failed to load merge join step XML: " + e.getCause(), e);
} Prevention
- Do not hand-edit .ktr XML; edit via Spoon.
- Resolve git/SVN merge conflicts on .ktr files by regenerating them in Spoon.
- Keep Kettle/Pentaho client and engine versions aligned.
- Validate XML well-formedness before loading programmatically.
When it happens
Trigger: loadXML is called on a transformation file whose <merge_join> XML node is malformed or whose sub-elements make XMLHandler.getTagValue/getStepIOMeta().getInfoStreams() throw — e.g. corrupted .ktr XML, hand-edited XML, or an XML structure from an incompatible Pentaho/Kettle version.
Common situations: Manually editing a .ktr and breaking the step1/step2/join_type tags; opening a transformation saved by a newer Kettle version in an older one; truncated or SVN/git-merge-conflicted transformation files.
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
- MergeJoinMeta.Exception.UnexpectedErrorReadingStepInfo
- MergeRowsMeta.Exception.UnableToLoadStepInfo
- Unable to load step info from XML
- Unable to load step info from XML
- AccessInputMeta.Exception.ErrorReadingRepository
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/153c2032652bdd03.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/mergejoin/MergeJoinMeta.java:207
allocate( nrKeys1, nrKeys2 );
for ( int i = 0; i < nrKeys1; i++ ) {
Node keynode = XMLHandler.getSubNodeByNr( keysNode1, "key", i );
keyFields1[i] = XMLHandler.getNodeValue( keynode );
}
for ( int i = 0; i < nrKeys2; i++ ) {
Node keynode = XMLHandler.getSubNodeByNr( keysNode2, "key", i );
keyFields2[i] = XMLHandler.getNodeValue( keynode );
}
List<StreamInterface> infoStreams = getStepIOMeta().getInfoStreams();
infoStreams.get( 0 ).setSubject( XMLHandler.getTagValue( stepnode, "step1" ) );
infoStreams.get( 1 ).setSubject( XMLHandler.getTagValue( stepnode, "step2" ) );
joinType = XMLHandler.getTagValue( stepnode, "join_type" );
} catch ( Exception e ) {
throw new KettleXMLException(
BaseMessages.getString( PKG, "MergeJoinMeta.Exception.UnableToLoadStepInfo" ), e );
}
}
public void setDefault() {
joinType = join_types[0];
allocate( 0, 0 );
}
public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException {
try {
int nrKeys1 = rep.countNrStepAttributes( id_step, "keys_1" );
int nrKeys2 = rep.countNrStepAttributes( id_step, "keys_2" );
allocate( nrKeys1, nrKeys2 );
for ( int i = 0; i < nrKeys1; i++ ) {
keyFields1[i] = rep.getStepAttributeString( id_step, i, "keys_1" );View on GitHub (pinned to f3058517a1)