pentaho/pentaho-kettle · error · KettleXMLException

Unable to load job entry of type 'table exists' from XML…

Error message

Unable to load job entry of type 'table exists' from XML node

What it means

KettleXMLException thrown by JobEntryMysqlBulkFile.loadXML() when parsing the XML node for this job entry (historically labeled 'table exists') fails. The message string is a copy-paste leftover; it is actually the MySQL bulk-file (export table to file) entry. It means the XML could not be read into entry fields.

Solutions

  1. Inspect the XML node for the entry and restore missing/mistyped tags (e.g. correct <connection> name).
  2. Regenerate the entry in Spoon to produce valid XML.
  3. Add the referenced shared connection to the job's database metadata list.
  4. Align Kettle versions between file producer and consumer.

Example fix

// before
<connction>MySQL-Local</connction>
// after
<connection>MySQL-Local</connection>
Defensive patterns

Strategy: try-catch

Validate before calling

// before load
if ( entrynode == null ) throw new KettleXMLException( "null entry node for MySQL bulk file entry" );
if ( XMLHandler.getTagValue( entrynode, "connection" ) == null ) throw new KettleXMLException( "missing <connection> tag" );

Type guard

boolean ok = (entrynode != null && XMLHandler.getTagValue( entrynode, "addfiletoresult" ) != null);

Try / catch

try { jobEntry.loadXML( entrynode, databases, metaStore ); } catch ( KettleXMLException e ) { logError( "Cannot parse entry XML: " + e.getMessage(), e ); }

Prevention

When it happens

Trigger: Loading a .kjb containing this entry when XMLHandler.getTagValue throws or DatabaseMeta.findDatabase fails — wrong/missing tags (schemaname, tablename, filename, outdumpvalue, iffileexists, connection, addfiletoresult) or null entrynode.

Common situations: Truncated or hand-edited .kjb; file generated by a different Pentaho version with renamed tags; the named connection is not present in the databases list.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/dcf98ff0c4377c96. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/mysqlbulkfile/JobEntryMysqlBulkFile.java:147

    try {
      super.loadXML( entrynode, databases, slaveServers );
      schemaname = XMLHandler.getTagValue( entrynode, "schemaname" );
      tablename = XMLHandler.getTagValue( entrynode, "tablename" );
      filename = XMLHandler.getTagValue( entrynode, "filename" );
      separator = XMLHandler.getTagValue( entrynode, "separator" );
      enclosed = XMLHandler.getTagValue( entrynode, "enclosed" );
      lineterminated = XMLHandler.getTagValue( entrynode, "lineterminated" );
      limitlines = XMLHandler.getTagValue( entrynode, "limitlines" );
      listcolumn = XMLHandler.getTagValue( entrynode, "listcolumn" );
      highpriority = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "highpriority" ) );
      optionenclosed = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "optionenclosed" ) );
      outdumpvalue = Const.toInt( XMLHandler.getTagValue( entrynode, "outdumpvalue" ), -1 );
      iffileexists = Const.toInt( XMLHandler.getTagValue( entrynode, "iffileexists" ), -1 );
      String dbname = XMLHandler.getTagValue( entrynode, "connection" );
      connection = DatabaseMeta.findDatabase( databases, dbname );
      addfiletoresult = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "addfiletoresult" ) );
    } catch ( KettleException e ) {
      throw new KettleXMLException( "Unable to load job entry of type 'table exists' from XML node", e );
    }
  }

  public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
    List<SlaveServer> slaveServers ) throws KettleException {
    try {
      schemaname = rep.getJobEntryAttributeString( id_jobentry, "schemaname" );
      tablename = rep.getJobEntryAttributeString( id_jobentry, "tablename" );
      filename = rep.getJobEntryAttributeString( id_jobentry, "filename" );
      separator = rep.getJobEntryAttributeString( id_jobentry, "separator" );
      enclosed = rep.getJobEntryAttributeString( id_jobentry, "enclosed" );
      lineterminated = rep.getJobEntryAttributeString( id_jobentry, "lineterminated" );
      limitlines = rep.getJobEntryAttributeString( id_jobentry, "limitlines" );
      listcolumn = rep.getJobEntryAttributeString( id_jobentry, "listcolumn" );
      highpriority = rep.getJobEntryAttributeBoolean( id_jobentry, "highpriority" );
      optionenclosed = rep.getJobEntryAttributeBoolean( id_jobentry, "optionenclosed" );

      outdumpvalue = (int) rep.getJobEntryAttributeInteger( id_jobentry, "outdumpvalue" );

View on GitHub (pinned to f3058517a1)