pentaho/pentaho-kettle · error · KettleException

Mail.Error.MailServerEmpty

Error message

Mail.Error.MailServerEmpty

What it means

In Mail.processRow(), the SMTP server name is read from the incoming row at data.indexOfServer; if it is null or empty (Utils.isEmpty) the step throws KettleException 'Mail.Error.MailServerEmpty' because no SMTP host was supplied for sending.

Solutions

  1. Set a static SMTP server in the step dialog instead of reading it from the row, if it never varies per row.
  2. Ensure the server field is populated for every row — filter or default empty values upstream.
  3. If using a variable for the server field, define it (kettle.properties / transformation parameter).
  4. Verify the correct column is selected as the 'SMTP server' source field in the dialog.

Example fix

// before
<server_field>smtp_host</server_field>   <!-- column empty in data -->
// after: either fill the column upstream or use a static server
<server>smtp.example.com</server>
Defensive patterns

Strategy: validation

Validate before calling

// before the Mail step
FilterRows: smtp_server IS NOT NULL AND LENGTH(TRIM(smtp_server)) > 0
// or set a constant if the server never varies per row

Try / catch

try {
  mail.processRow();
} catch (KettleException e) {
  if (e.getMessage().contains("MailServerEmpty")) {
    logError("SMTP server missing in row or configuration");
  }
  throw e;
}

Prevention

When it happens

Trigger: The Mail step is configured with the SMTP server taken from a field, and the current row's server field is empty/null at data.indexOfServer.

Common situations: Server column missing values in source data; wrong column mapped as the server field; variable-substituted server field resolves to empty when the variable is undefined; environment switch (no SMTP host recorded for this environment).

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/db8bdb2354b0ac8c. Report an issue: GitHub.

Appendix: source

Thrown at plugins/mail/impl/src/main/java/org/pentaho/di/trans/steps/mail/Mail.java:158

      // reply addresses
      String mailReplyToAddresses = null;
      if ( data.indexOfReplyToAddresses > -1 ) {
        mailReplyToAddresses = data.previousRowMeta.getString( r, data.indexOfReplyToAddresses );
      }

      String contactPerson = null;
      if ( data.indexOfContactPerson > -1 ) {
        contactPerson = data.previousRowMeta.getString( r, data.indexOfContactPerson );
      }
      String contactPhone = null;
      if ( data.indexOfContactPhone > -1 ) {
        contactPhone = data.previousRowMeta.getString( r, data.indexOfContactPhone );
      }

      String serverName = data.previousRowMeta.getString( r, data.indexOfServer );
      if ( Utils.isEmpty( serverName ) ) {
        throw new KettleException( "Mail.Error.MailServerEmpty" );
      }
      int port = -1;
      if ( data.indexOfPort > -1 ) {
        port = Const.toInt( "" + data.previousRowMeta.getInteger( r, data.indexOfPort ), -1 );
      }

      String authUser = null;
      if ( data.indexOfAuthenticationUser > -1 ) {
        authUser = data.previousRowMeta.getString( r, data.indexOfAuthenticationUser );
      }
      String authPass = null;
      if ( data.indexOfAuthenticationPass > -1 ) {
        authPass = Utils.resolvePassword( getParentVariableSpace(), data.previousRowMeta.getString( r, data.indexOfAuthenticationPass ) );
      }

      String subject = null;
      if ( data.indexOfSubject > -1 ) {
        subject = data.previousRowMeta.getString( r, data.indexOfSubject );

View on GitHub (pinned to f3058517a1)