pentaho/pentaho-kettle · error · KettleException

ExecSQLRow.Log.EmptySQLFromFile

Error message

ExecSQLRow.Log.EmptySQLFromFile

What it means

KettleException thrown by ExecSQLRow.processRow() when 'SQL from file' is enabled but the value of the SQL field in the current row is empty. Since the value is used as a filename of a script to execute, an empty value means there is nothing to execute. Note the message key is a Log key but it is thrown as a hard error here.

Solutions

  1. Add a Filter rows step upstream to drop rows where the filename field is null/empty before the ExecSQLRow step.
  2. Fix the data source so every row contains a valid script filename.
  3. If the field actually contains SQL text (not a filename), disable 'SQL from file' in the step dialog.
  4. Use a Value Mapper / NVL step to substitute a default filename for empty values.

Example fix

// upstream fix: filter nulls before the step
// Filter rows: filename IS NOT NULL AND filename <> ''
// or in code ensure non-empty before executing:
String sql = row.getString(fieldName, "");
if (sql == null || sql.isEmpty()) { throw new IllegalArgumentException("empty sql filename"); }
Defensive patterns

Strategy: validation

Validate before calling

String filename = row.getString(sqlField, "");
if (filename == null || filename.trim().isEmpty()) {
  throw new IllegalStateException("Row has empty SQL filename; filter it upstream");
}

Try / catch

try { trans.execute(...); } catch (KettleException e) { if (e.getMessage().contains("EmptySQLFromFile")) { log.error("empty filename row reached ExecSQLRow"); } }

Prevention

When it happens

Trigger: meta.isSqlFromfile() is true and getInputRowMeta().getString(row, indexOfSQLFieldname) returns null or empty string for the incoming row, so Utils.isEmpty(sql) is true before data.db.execStatementsFromFile() is called.

Common situations: Source table/CSV has null or blank filename values; filter step missing so empty rows reach the step; sqlFromfile flag enabled accidentally while feeding actual SQL text (not filenames).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/execsqlrow/ExecSQLRow.java:125

      if ( data.indexOfSQLFieldname < 0 ) {
        data.indexOfSQLFieldname = this.getInputRowMeta().indexOfValue( meta.getSqlFieldName() );
        if ( data.indexOfSQLFieldname < 0 ) {
          // The field is unreachable !
          throw new KettleException( BaseMessages.getString( PKG, "ExecSQLRow.Exception.CouldnotFindField", meta
            .getSqlFieldName() ) );
        }
      }

    }

    // get SQL
    String sql = getInputRowMeta().getString( row, data.indexOfSQLFieldname );

    try {
      if ( meta.isSqlFromfile() ) {
        if ( Utils.isEmpty( sql ) ) {
          // empty filename
          throw new KettleException( BaseMessages.getString( PKG, "ExecSQLRow.Log.EmptySQLFromFile" ) );
        }
        if ( log.isDebug() ) {
          logDebug( BaseMessages.getString( PKG, "ExecSQLRow.Log.ExecutingSQLFromFile", sql ) );
        }
        data.result = data.db.execStatementsFromFile( getTransMeta().getBowl(), sql, meta.IsSendOneStatement() );
      } else {
        if ( log.isDebug() ) {
          logDebug( BaseMessages.getString( PKG, "ExecSQLRow.Log.ExecutingSQLScript" ) + Const.CR + sql );
        }
        if ( meta.IsSendOneStatement() ) {
          data.result = data.db.execStatement( sql );
        } else {
          data.result = data.db.execStatements( sql );
        }
      }

      RowMetaAndData add =
        getResultRow( data.result, meta.getUpdateField(), meta.getInsertField(), meta.getDeleteField(), meta

View on GitHub (pinned to f3058517a1)