pentaho/pentaho-kettle · error · KettleXMLException
JobEntryTruncateTables.UnableLoadXML
Error message
JobEntryTruncateTables.UnableLoadXML
What it means
JobEntryTruncateTables.loadXML() wraps any KettleException raised while parsing the job entry's XML <fields> nodes into a KettleXMLException with the localized message 'JobEntryTruncateTables.UnableLoadXML'. It is thrown when the XML representation of the 'truncate tables' job entry cannot be read — typically a malformed or missing <field> sub-node. The original exception is preserved as the cause.
Solutions
- Open the .kjb file in a text editor and fix or remove the malformed <field> entries under the truncate-tables job entry node.
- Recreate the job entry in Spoon so a well-formed XML block is regenerated.
- Check the cause chain (KettleXMLException.getCause()) to find the exact XMLHandler failure line.
- Verify the file was not truncated or re-encoded (BOM/charset issues) during transfer between systems.
Example fix
// before: hand-edited .kjb with missing <name> tag <field><schemaname>public</schemaname></field> // after <field><name>my_table</name><schemaname>public</schemaname></field>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the XML node before calling loadXML
Node fields = XMLHandler.getSubNode(entrynode, "fields");
if (fields == null) throw new KettleXMLException("Missing <fields> node");
int nr = XMLHandler.countNodes(fields, "field");
for (int i = 0; i < nr; i++) {
Node f = XMLHandler.getSubNodeByNr(fields, "field", i);
if (f == null || XMLHandler.getTagValue(f, "name") == null)
throw new KettleXMLException("Field " + i + " missing <name>");
} Type guard
boolean isValidFieldsNode(Node entrynode) {
Node fields = XMLHandler.getSubNode(entrynode, "fields");
return fields != null && XMLHandler.countNodes(fields, "field") > 0;
} Try / catch
try {
jobEntry.loadXML(entrynode, databases, metaStore);
} catch ( KettleXMLException e ) {
logError("Corrupt truncate-tables XML: " + e.getCause().getMessage(), e);
// skip entry, load from repository, or abort the job load
} Prevention
- Never hand-edit .kjb files; edit through Spoon.
- Keep writer and reader Pentaho/Kettle versions aligned.
- Keep .kjb files in version control to diff against known-good versions.
- Validate XML well-formedness after any external transformation of job files.
When it happens
Trigger: Calling loadXML(...) with an XML node whose <fields> element or its <field> children are missing/malformed, so XMLHandler.getSubNodeByNr/getTagValue throws, or the declared nrFields does not match the actual number of <field> nodes.
Common situations: Hand-edited or truncated .kjb job files; XML produced by a different Pentaho/Kettle version with changed field names; corrupted repository-export XML; copy-paste errors in the field/schemaname attributes.
Related errors
- JobEntryWaitForSQL.UnableLoadXML
- JobPGPEncryptFiles.Error.Exception.UnableLoadXML
- Unable to load job entry of type 'unzip' from XML node
- Unable to load job entry of type 'wait for file' from XML…
- AddSequenceMeta.Exception.ErrorLoadingStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9d7789db13c7817a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/truncatetables/JobEntryTruncateTables.java:141
String dbname = XMLHandler.getTagValue( entrynode, "connection" );
this.connection = DatabaseMeta.findDatabase( databases, dbname );
this.argFromPrevious = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "arg_from_previous" ) );
Node fields = XMLHandler.getSubNode( entrynode, "fields" );
// How many field arguments?
int nrFields = XMLHandler.countNodes( fields, "field" );
allocate( nrFields );
// Read them all...
for ( int i = 0; i < nrFields; i++ ) {
Node fnode = XMLHandler.getSubNodeByNr( fields, "field", i );
this.arguments[i] = XMLHandler.getTagValue( fnode, "name" );
this.schemaname[i] = XMLHandler.getTagValue( fnode, "schemaname" );
}
} catch ( KettleException e ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "JobEntryTruncateTables.UnableLoadXML" ), e );
}
}
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
connection = rep.loadDatabaseMetaFromJobEntryAttribute( id_jobentry, "connection", "id_database", databases );
this.argFromPrevious = rep.getJobEntryAttributeBoolean( id_jobentry, "arg_from_previous" );
// How many arguments?
int argnr = rep.countNrJobEntryAttributes( id_jobentry, "name" );
allocate( argnr );
// Read them all...
for ( int a = 0; a < argnr; a++ ) {
this.arguments[a] = rep.getJobEntryAttributeString( id_jobentry, a, "name" );
this.schemaname[a] = rep.getJobEntryAttributeString( id_jobentry, a, "schemaname" );
}View on GitHub (pinned to f3058517a1)