pentaho/pentaho-kettle · error · KettleXMLException
JobFoldersCompare.Meta.UnableLoadXML
Error message
JobFoldersCompare.Meta.UnableLoadXML
What it means
Thrown by JobEntryFoldersCompare.loadXML when parsing the job entry's XML node fails with a KettleXMLException. The message is a localized bundle key (JobFoldersCompare.Meta.UnableLoadXML) with the original message substituted. It means the 'Compare Folders' entry could not be read from a .kjb XML document.
Solutions
- Open the .kjb file in an XML validator/editor and fix the malformed entry node (compareonly, wildcard, filename1, filename2 tags).
- Check xe.getMessage() in the wrapped exception for the exact XML parse error and line.
- Re-export the job from Spoon to regenerate valid XML.
- Ensure the file encoding matches the declared encoding (UTF-8) and the file is not truncated.
Example fix
// before: hand-edited node missing closing tag <folders_compare><filename1>/a</filename1> // after: valid complete node <folders_compare> <compareonly>N</compareonly> <filename1>/data/a</filename1> <filename2>/data/b</filename2> </folders_compare>
Defensive patterns
Strategy: validation
Validate before calling
// validate XML before loading
Document doc = XMLHandler.loadXMLFile(kjbInputStream);
if (doc == null) throw new KettleException("Invalid or empty .kjb XML");
Node entryNode = XMLHandler.getSubNode(doc, "entry");
if (entryNode == null) throw new KettleException("Missing <entry> node"); Try / catch
try {
entry.loadXML(entryNode, databases, slaveServers, rep, metaStore);
} catch (KettleXMLException e) {
logError("FoldersCompare XML load failed: " + e.getMessage());
// fix or re-export the .kjb file
} Prevention
- Never hand-edit .kjb files; edit in Spoon only.
- Run XML files through a validator after any external manipulation.
- Transfer .kjb files in binary mode to avoid truncation/encoding damage.
- Pin Pentaho versions between export and load to avoid schema drift.
When it happens
Trigger: Calling loadXML on JobEntryFoldersCompare when XMLHandler.getTagValue/getSubNode throws KettleXMLException — malformed XML, wrong node structure, or an XML parsing error inside the entry's <entry> block.
Common situations: Hand-edited .kjb files with invalid XML; job files truncated by a failed transfer; version drift where the XML schema changed; copy-pasting an entry node from another job with mismatched tags.
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
- ERROR_0001
- JobDosToUnix.Error.Exception.UnableLoadXML
- JobEntryDeleteFolders.UnableToLoadFromXml
- JobEntryDeleteResultFilenames.CanNotLoadFromXML
- JobEntrySimple.Error.Exception.UnableLoadXML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/a99110d5e6d7f77e.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/folderscompare/JobEntryFoldersCompare.java:138
parentJobMeta.getNamedClusterEmbedManager().registerUrl( filename2 );
}
return retval.toString();
}
public void loadXML( Node entrynode, List<DatabaseMeta> databases, List<SlaveServer> slaveServers,
Repository rep, IMetaStore metaStore ) throws KettleXMLException {
try {
super.loadXML( entrynode, databases, slaveServers );
includesubfolders = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "include_subfolders" ) );
comparefilecontent = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "compare_filecontent" ) );
comparefilesize = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "compare_filesize" ) );
compareonly = XMLHandler.getTagValue( entrynode, "compareonly" );
wildcard = XMLHandler.getTagValue( entrynode, "wildcard" );
filename1 = XMLHandler.getTagValue( entrynode, "filename1" );
filename2 = XMLHandler.getTagValue( entrynode, "filename2" );
} catch ( KettleXMLException xe ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "JobFoldersCompare.Meta.UnableLoadXML", xe
.getMessage() ) );
}
}
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
includesubfolders = rep.getJobEntryAttributeBoolean( id_jobentry, "include_subfolders" );
comparefilecontent = rep.getJobEntryAttributeBoolean( id_jobentry, "compare_filecontent" );
comparefilesize = rep.getJobEntryAttributeBoolean( id_jobentry, "compare_filesize" );
compareonly = rep.getJobEntryAttributeString( id_jobentry, "compareonly" );
wildcard = rep.getJobEntryAttributeString( id_jobentry, "wildcard" );
filename1 = rep.getJobEntryAttributeString( id_jobentry, "filename1" );
filename2 = rep.getJobEntryAttributeString( id_jobentry, "filename2" );
} catch ( KettleException dbe ) {
throw new KettleException( BaseMessages.getString( PKG, "JobFoldersCompare.Meta.UnableLoadRep", ""
+ id_jobentry, dbe.getMessage() ) );View on GitHub (pinned to f3058517a1)