pentaho/pentaho-kettle · error · KettleXMLException

JobEntryWaitForSQL.UnableLoadXML

Error message

JobEntryWaitForSQL.UnableLoadXML

What it means

JobEntryWaitForSQL.loadXML() wraps a KettleException raised while parsing the 'wait for SQL' entry's XML into a KettleXMLException with the localized message 'JobEntryWaitForSQL.UnableLoadXML'. It means the XML node for this job entry (connection, SQL script, timeouts, flags) could not be parsed.

Solutions

  1. Open the .kjb and repair the <entry type='WAIT_FOR_SQL'> node; compare against a working job from the same version.
  2. Recreate the Wait For SQL entry in Spoon so valid XML is written.
  3. Use e.getCause() to pinpoint which XMLHandler call failed and which tag is at fault.
  4. Ensure the Kettle version reading the file matches (or is newer than) the version that wrote it.

Example fix

// before: missing connection node in .kjb
<entry type='WAIT_FOR_SQL'><sql>select 1</sql></entry>
// after
<entry type='WAIT_FOR_SQL'><connection>prod_db</connection><sql>select 1</sql></entry>
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate wait-for-SQL XML structure before loadXML
if ( XMLHandler.getSubNode(entrynode, "connection") == null )
  throw new KettleXMLException("wait-for-sql entry missing <connection>");
if ( XMLHandler.getTagValue(entrynode, "sql") == null )
  throw new KettleXMLException("wait-for-sql entry missing <sql>");

Type guard

boolean isValidWaitForSqlNode(Node entrynode) {
  return entrynode != null
    && XMLHandler.getSubNode(entrynode, "connection") != null
    && XMLHandler.getTagValue(entrynode, "sql") != null;
}

Try / catch

try {
  jobEntry.loadXML(entrynode, databases, slaveServers, rep, metaStore);
} catch ( KettleXMLException e ) {
  logError("Wait-for-SQL XML load failed: " + e.getCause().getMessage(), e);
  // abort job load or substitute a corrected node
}

Prevention

When it happens

Trigger: Calling loadXML(...) with an entrynode that is missing required sub-nodes (e.g. <connection>, <sql>, 'maximum_timeout', 'clear_result_rows') or contains invalid values, so XMLHandler throws KettleException.

Common situations: Hand-edited or partial .kjb files; XML exported from a newer Kettle with attributes this version cannot parse; corrupted export files; renamed tags across versions.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/job/entries/waitforsql/JobEntryWaitForSQL.java:252

      super.loadXML( entrynode, databases, slaveServers );
      String dbname = XMLHandler.getTagValue( entrynode, "connection" );
      connection = DatabaseMeta.findDatabase( databases, dbname );
      schemaname = XMLHandler.getTagValue( entrynode, "schemaname" );
      tablename = XMLHandler.getTagValue( entrynode, "tablename" );
      successCondition =
        getSucessConditionByCode( Const.NVL( XMLHandler.getTagValue( entrynode, "success_condition" ), "" ) );
      rowsCountValue = Const.NVL( XMLHandler.getTagValue( entrynode, "rows_count_value" ), "0" );
      iscustomSQL = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "is_custom_sql" ) );
      isUseVars = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "is_usevars" ) );
      customSQL = XMLHandler.getTagValue( entrynode, "custom_sql" );
      isAddRowsResult = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "add_rows_result" ) );
      maximumTimeout = XMLHandler.getTagValue( entrynode, "maximum_timeout" );
      checkCycleTime = XMLHandler.getTagValue( entrynode, "check_cycle_time" );
      successOnTimeout = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "success_on_timeout" ) );
      isClearResultList = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "clear_result_rows" ) );

    } catch ( KettleException e ) {
      throw new KettleXMLException( BaseMessages.getString( PKG, "JobEntryWaitForSQL.UnableLoadXML" ), e );
    }
  }

  @Override
  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 );

      schemaname = rep.getJobEntryAttributeString( id_jobentry, "schemaname" );
      tablename = rep.getJobEntryAttributeString( id_jobentry, "tablename" );
      successCondition =
        getSuccessConditionByCode( Const.NVL(
          rep.getJobEntryAttributeString( id_jobentry, "success_condition" ), "" ) );
      rowsCountValue = rep.getJobEntryAttributeString( id_jobentry, "rows_count_value" );
      iscustomSQL = rep.getJobEntryAttributeBoolean( id_jobentry, "is_custom_sql" );
      isUseVars = rep.getJobEntryAttributeBoolean( id_jobentry, "is_usevars" );
      isAddRowsResult = rep.getJobEntryAttributeBoolean( id_jobentry, "add_rows_result" );

View on GitHub (pinned to f3058517a1)