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
- Open the .kjb and repair the <entry type='WAIT_FOR_SQL'> node; compare against a working job from the same version.
- Recreate the Wait For SQL entry in Spoon so valid XML is written.
- Use e.getCause() to pinpoint which XMLHandler call failed and which tag is at fault.
- 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
- Author jobs in Spoon; never hand-edit the WAIT_FOR_SQL XML block.
- Confirm reader Kettle version supports tags written by the authoring version.
- Diff suspect .kjb files against a known-good job.
- Catch KettleXMLException and inspect the cause to locate the broken tag.
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
- JobEntryTruncateTables.UnableLoadXML
- JobPGPEncryptFiles.Error.Exception.UnableLoadXML
- Unable to load job entry of type 'unzip' from XML node
- Unable to load job entry of type 'wait for file' from XML…
- AddSequenceMeta.Exception.ErrorLoadingStepInfo
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)