pentaho/pentaho-kettle · error · KettleXMLException
FuzzyMatchMeta.Exception.UnableToLoadStepInfoFromXML
Error message
FuzzyMatchMeta.Exception.UnableToLoadStepInfoFromXML
What it means
loadXML() delegates parsing of the step's <field> XML configuration to readData(); when any exception occurs while reading FuzzyMatch metadata from the transformation XML it is re-thrown as a KettleXMLException with message 'FuzzyMatchMeta.Exception.UnableToLoadStepInfoFromXML'. It indicates the step's serialized definition in the .ktr file could not be parsed.
Solutions
- Open the .ktr in Spoon and fix/replace the FuzzyMatch step configuration; re-enter lookup and return field settings
- Validate the XML structure of the step node (fields have 'name', 'rename' attributes; lookup nodes exist)
- Compare the failing .ktr with a working one and restore the missing step attributes
- Check Pentaho/Data Integration version compatibility; re-save with the current version
- As a last resort, delete the FuzzyMatch step and re-add it, reconnecting hops
Example fix
// before (broken XML) <fields> <field/> </fields> // after <fields> <field name="lname" rename="lname_match"/> </fields>
Defensive patterns
Strategy: try-catch
Validate before calling
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("trans.ktr"));
NodeList steps = doc.getElementsByTagName("step");
for (int i = 0; i < steps.getLength(); i++) {
if ("FuzzyMatch".equals(((Element) steps.item(i)).getElementsByTagName("type").item(0).getTextContent())) {
if (((Element) steps.item(i)).getElementsByTagName("lookup").getLength() == 0)
throw new IllegalStateException("FuzzyMatch step XML missing lookup fields; fix .ktr before loading");
}
} Try / catch
try {
meta.loadXML(stepnode, databases, metaStore);
} catch (KettleXMLException e) {
log.error("Failed to load FuzzyMatch step from XML: " + e.getCause(), e);
meta = new FuzzyMatchMeta(); // fall back to defaults and reconfigure
} Prevention
- Never hand-edit .ktr files; use Spoon for all step configuration changes
- Keep transformation files in version control and avoid manual merges of step XML
- Validate .ktr files after version upgrades before relying on them
- Avoid editing transformations with different Pentaho versions simultaneously
When it happens
Trigger: Calling FuzzyMatchMeta.loadXML(...) on a corrupted or hand-edited .ktr XML: missing/invalid attributes for lookup fields, wrong element structure, or an exception thrown by the XML node traversal (e.g. NullPointer on missing nodes).
Common situations: Opening a transformation saved by a different Pentaho version whose step XML schema changed; manual edit of the .ktr that removed <lookup> or <value> child nodes; truncated XML from bad source control merge.
Related errors
- GetXMLDataMeta.Exception.ErrorLoadingXML (localized message…
- GetPreviousRowFieldMeta.Exception.UnableToReadStepInfoFromXM…
- InsertUpdateMeta.Exception.UnableToReadStepInfoFromXML
- JsonInputMeta.Exception.ErrorLoadingXML
- LoadFileInputMeta.Exception.ErrorLoadingXML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/24fdf13f7cbeeec4.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/fuzzymatch/FuzzyMatchMeta.java:407
algorithm = getAlgorithmTypeByCode( Const.NVL( XMLHandler.getTagValue( stepnode, "algorithm" ), "" ) );
Node lookup = XMLHandler.getSubNode( stepnode, "lookup" );
int nrvalues = XMLHandler.countNodes( lookup, "value" );
allocate( nrvalues );
for ( int i = 0; i < nrvalues; i++ ) {
Node vnode = XMLHandler.getSubNodeByNr( lookup, "value", i );
value[i] = XMLHandler.getTagValue( vnode, "name" );
valueName[i] = XMLHandler.getTagValue( vnode, "rename" );
if ( valueName[i] == null ) {
valueName[i] = value[i]; // default: same name to return!
}
}
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString(
PKG, "FuzzyMatchMeta.Exception.UnableToLoadStepInfoFromXML" ), e );
}
}
private static String getAlgorithmTypeCode( int i ) {
if ( i < 0 || i >= algorithmCode.length ) {
return algorithmCode[0];
}
return algorithmCode[i];
}
public void setDefault() {
value = null;
valueName = null;
separator = DEFAULT_SEPARATOR;
closervalue = true;
minimalValue = "0";
maximalValue = "1";View on GitHub (pinned to f3058517a1)