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

  1. Open the .kjb file in a text editor and validate the <entry type="TABLE_EXISTS"> XML block is well-formed
  2. Restore the job file from version control or an earlier good copy
  3. Load the job in Spoon and re-save it to regenerate clean XML
  4. Check the chained cause (e) in the KettleXMLException for the exact parsing error and line
  5. 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

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


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)