pentaho/pentaho-kettle · error · KettleXMLException

JobEntryColumnsExist.Meta.UnableLoadXml

Error message

JobEntryColumnsExist.Meta.UnableLoadXml

What it means

JobEntryColumnsExist.loadXML wraps any KettleException thrown while decoding the entry's XML (count of fields and per-field 'name' tags) into this KettleXMLException. It means the 'Columns exist in a table' entry's XML fragment could not be parsed into its arguments array.

Solutions

  1. Inspect the entry XML: it must contain <fields> with <field><name>…</name></field> children
  2. Recreate the 'Columns exist in a table' entry in Spoon and re-save
  3. Load the job in the PDI version that produced it, then re-export
  4. Check the chained exception for the exact failing XMLHandler call

Example fix

// before
<connection/><schema/><table/> <!-- <fields> block accidentally deleted -->
// after
<connection/><schema/><table/><fields><field><name>id</name></field><field><name>amount</name></field></fields>
Defensive patterns

Strategy: try-catch

Validate before calling

org.w3c.dom.Node fields = XMLHandler.getSubNode(entryNode, "fields");
if (fields == null) throw new IllegalArgumentException("ColumnsExist entry XML missing <fields>");

Try / catch

try {
  entry.loadXML(entryNode, databases, slaveServers, metaStore);
} catch (KettleXMLException e) {
  log.error("Cannot parse ColumnsExist entry XML: " + e.getCause(), e);
}

Prevention

When it happens

Trigger: Calling loadXML when XMLHandler calls for the <fields>/<field> nodes or 'name' tags fail — missing fields node, wrong structure, or a throwing XMLHandler operation.

Common situations: Job file edited by hand removing <fields>; entry XML copied from a different entry type; export/import across PDI versions with changed layout; truncated file.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/columnsexist/JobEntryColumnsExist.java:132

      schemaname = XMLHandler.getTagValue( entrynode, "schemaname" );

      String dbname = XMLHandler.getTagValue( entrynode, "connection" );
      connection = DatabaseMeta.findDatabase( databases, dbname );

      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 );
        arguments[i] = XMLHandler.getTagValue( fnode, "name" );
      }

    } catch ( KettleException e ) {
      throw new KettleXMLException( BaseMessages.getString( PKG, "JobEntryColumnsExist.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 );

      // How many arguments?
      int argnr = rep.countNrJobEntryAttributes( id_jobentry, "name" );
      arguments = new String[argnr];

      // Read them all...
      for ( int a = 0; a < argnr; a++ ) {
        arguments[a] = rep.getJobEntryAttributeString( id_jobentry, a, "name" );

View on GitHub (pinned to f3058517a1)