pentaho/pentaho-kettle · error · KettleException

Mail.Log.DestinationFieldEmpty

Error message

Mail.Log.DestinationFieldEmpty

What it means

The Pentaho Kettle Mail step throws this when the transformation metadata has no destination field configured. validateMetaFields, called at the start of processRow, checks meta.getDestination() with Utils.isEmpty and aborts the step because the mail step cannot determine the recipient(s) without it. It is a fail-fast metadata validation before any row processing or SMTP activity.

Solutions

  1. Open the Mail step dialog and set the Destination field (or the field name holding the destination addresses).
  2. If constructing MailMeta in code, call meta.setDestination("YourFieldOrAddress") before executing.
  3. Verify the transformation XML exports the destination attribute correctly; re-save the step and re-export.
  4. If recipients are genuinely not needed, ensure this is the intended behavior — the step requires a destination unconditionally.

Example fix

// before (programmatic MailMeta)
MailMeta meta = new MailMeta();
meta.setReplyAddress("reply@corp.com");
// after
MailMeta meta = new MailMeta();
meta.setDestination("destField");
meta.setReplyAddress("reply@corp.com");
Defensive patterns

Strategy: validation

Validate before calling

// Before executing the transformation, check the metadata
if ( meta.getDestination() == null || meta.getDestination().trim().isEmpty() ) {
  throw new IllegalArgumentException("Mail step: destination field is required");
}

Try / catch

try { transformation.execute(); } catch ( KettleException e ) { if ( e.getMessage().contains("DestinationFieldEmpty") ) { /* reconfigure MailMeta.setDestination */ } else { throw e; } }

Prevention

When it happens

Trigger: Running the Mail transformation step with the 'Destination' (to-address / destination field) setting left empty in the step dialog; the destination field name in MailMeta is blank or null when processRow invokes validateMetaFields.

Common situations: Importing a transformation from another environment where the Mail step dialog was partially filled; cloning a step and deleting the destination field; building MailMeta programmatically and forgetting setDestination(); upgrading jobs where the field mapping was lost.

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

Appendix: source

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

      }
      data.zipFileLimit = Const.toLong( environmentSubstitute( meta.getZipLimitSize() ), 0 );
      if ( data.zipFileLimit > 0 ) {
        data.zipFileLimit = data.zipFileLimit * 1048576; // Mo
      }

      if ( !meta.isZipFilenameDynamic() ) {
        data.ZipFilename = environmentSubstitute( meta.getZipFilename() );
      }
      // Attached files
      processAttachedFiles();
    }
  }

  @VisibleForTesting
  void validateMetaFields( MailMeta meta ) throws KettleException {
    // Check is filename field is provided
    if ( Utils.isEmpty( meta.getDestination() ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.DestinationFieldEmpty" ) );
    }

    // Check is replyname field is provided
    if ( Utils.isEmpty( meta.getReplyAddress() ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.ReplyFieldEmpty" ) );
    }

    // Check is SMTP server is provided
    if ( Utils.isEmpty( meta.getServer() ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.ServerFieldEmpty" ) );
    }

    // Check Attached filenames when dynamic
    if ( meta.isDynamicFilename() && Utils.isEmpty( meta.getDynamicFieldname() ) ) {
      throw new KettleException( BaseMessages.getString( PKG, "Mail.Log.DynamicFilenameFieldEmpty" ) );
    }

    // Check Attached zipfilename when dynamic

View on GitHub (pinned to f3058517a1)