pentaho/pentaho-kettle · error · KettleXMLException
TableExists.Meta.UnableLoadXml
Error message
TableExists.Meta.UnableLoadXml
What it means
JobEntryTableExists.loadXML wraps any KettleException raised while parsing the job entry's XML node (tablename, schemaname, connection tags) into a KettleXMLException with the localized 'TableExists.Meta.UnableLoadXml' message and the original as cause. It indicates the XML representation of this entry could not be deserialized.
Solutions
- Open the .kjb file in a text editor and validate the <entry type="TABLE_EXISTS"> XML block is well-formed
- Restore the job file from version control or an earlier good copy
- Load the job in Spoon and re-save it to regenerate clean XML
- Check the chained cause (e) in the KettleXMLException for the exact parsing error and line
- If a connection lookup is the problem, ensure the database connection is defined in the job/shared XML
Example fix
// before: hand-edited XML with broken tag <tablename>&db_table</tablename> <!-- unescaped & --> // after <tablename>my_table</tablename>
Defensive patterns
Strategy: try-catch
Validate before calling
// Java: sanity-check the XML node before loadXML
if (entrynode == null || XMLHandler.getTagValue(entrynode, "connection") == null
&& XMLHandler.getTagValue(entrynode, "tablename") == null) {
throw new KettleXMLException("TABLE_EXISTS entry node missing required tags");
} Type guard
if (entrynode != null && "TABLE_EXISTS".equals(XMLHandler.getTagValue(entrynode, "type"))) { /* safe */ } Try / catch
try {
entry.loadXML(entrynode, databases, slaveServers, rep, metaStore);
} catch (KettleXMLException e) {
logError("TableExists XML load failed: " + e.getCause(), e);
// fall back to defaults or abort job load
} Prevention
- Validate .kjb files as XML after manual edits
- Keep job files in version control with clean merges
- Avoid loading files produced by newer Pentaho versions into older ones
- Ensure referenced database connections exist in shared/job XML
When it happens
Trigger: Calling loadXML with a malformed entrynode: XMLHandler.getTagValue or DatabaseMeta.findDatabase throws, e.g. the node's nested content is invalid or the databases list processing fails.
Common situations: A hand-edited or truncated .kjb file missing/broken tags; the <connection> name refers to a database meta removed from the shared XML (findDatabase returning null is tolerated, but exceptions during parsing are not); version downgrade producing unexpected XML structure.
Related errors
- e.toString()
- ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node
- ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node
- ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node
- ERROR_0001_Cannot_Load_Job_Entry_From_Xml_Node
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/daa48601a9783f66.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/tableexists/JobEntryTableExists.java:96
retval.append( " " ).append( XMLHandler.addTagValue( "tablename", tablename ) );
retval.append( " " ).append( XMLHandler.addTagValue( "schemaname", schemaname ) );
retval.append( " " ).append(
XMLHandler.addTagValue( "connection", connection == null ? null : connection.getName() ) );
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 );
tablename = XMLHandler.getTagValue( entrynode, "tablename" );
schemaname = XMLHandler.getTagValue( entrynode, "schemaname" );
String dbname = XMLHandler.getTagValue( entrynode, "connection" );
connection = DatabaseMeta.findDatabase( databases, dbname );
} catch ( KettleException e ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "TableExists.Meta.UnableLoadXml" ), e );
}
}
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
tablename = rep.getJobEntryAttributeString( id_jobentry, "tablename" );
schemaname = rep.getJobEntryAttributeString( id_jobentry, "schemaname" );
connection = rep.loadDatabaseMetaFromJobEntryAttribute( id_jobentry, "connection", "id_database", databases );
} catch ( KettleDatabaseException dbe ) {
throw new KettleException(
BaseMessages.getString( PKG, "TableExists.Meta.UnableLoadRep", "" + id_jobentry ), dbe );
}
}
public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_job ) throws KettleException {
try {View on GitHub (pinned to f3058517a1)