pentaho/pentaho-kettle · error · KettleException
Mail.Error.MailDestinationEmpty
Error message
Mail.Error.MailDestinationEmpty
What it means
In Mail.processRow(), the step reads the destination e-mail address from the incoming row at data.indexOfDestination. If the value is null or empty (Utils.isEmpty), it throws a KettleException with the 'Mail.Error.MailDestinationEmpty' message because an e-mail cannot be sent without a recipient.
Solutions
- Filter or conditionally skip rows with empty destination before the Mail step (Filter rows / Stream Lookup guard).
- Map the correct column as the 'To' destination field in the step dialog.
- Provide a fallback/default address via a 'Value Mapper', 'If field value is null' step, or coalesce logic upstream.
- Handle the exception (or enable step error handling) to route bad rows to an error stream instead of failing the transformation.
Example fix
// before: mail step processes every row Mail -> (throws on empty address) // after: guard upstream Filter rows (destination IS NOT NULL AND destination <> '') -> Mail
Defensive patterns
Strategy: validation
Validate before calling
// before the Mail step, filter empty destinations FilterRows: destination IS NOT NULL AND LENGTH(TRIM(destination)) > 0
Try / catch
// step error handling: route rows that throw to an error stream
stepMeta.setSupportsErrorHandling(true);
// or catch in custom code:
try {
mail.processRow();
} catch (KettleException e) {
if (e.getMessage().contains("MailDestinationEmpty")) {
logError("Row has empty destination address: " + e.getMessage());
}
} Prevention
- Add a filter/null-guard step before any Mail step reading addresses from fields.
- Cleanse source data: coalesce missing e-mails to a default or a dead-letter flow.
- Enable error handling on the Mail step to divert bad rows instead of aborting.
- Verify the destination field mapping after any upstream schema change.
When it happens
Trigger: Executing the Mail step with 'To' taken from a field: the destination field exists but its value in the current row is empty/null — the row passes the field-existence check but the address column is blank.
Common situations: Upstream data has missing e-mail addresses (null contact column); a filter removed placeholder values; the wrong column is mapped as the destination field; test rows with empty addresses reach the step.
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
- JobGetMailsFromPOP.Error.MoveToIMAPFolderEmpty
- JobGetMailsFromPOP.Error.ReceivedDateSearchTermEmpty
- Mail.Error.MailServerEmpty
- At least one slave server is required to be present in…
- ChangeFileEncoding.Error.TargetFileIsEmpty
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/2bb86bab45b88989.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/mail/impl/src/main/java/org/pentaho/di/trans/steps/mail/Mail.java:124
if ( first ) {
first = false;
// get the RowMeta
data.previousRowMeta = getInputRowMeta().clone();
validateMetaFields( meta );
cacheFieldsPosition( meta, data );
checkEmbeddedImages( meta, data );
} // end if first
try {
// get values
String mailDestination = data.previousRowMeta.getString( r, data.indexOfDestination );
if ( Utils.isEmpty( mailDestination ) ) {
throw new KettleException( "Mail.Error.MailDestinationEmpty" );
}
String mailDestinationCc = null;
if ( data.indexOfDestinationCc > -1 ) {
mailDestinationCc = data.previousRowMeta.getString( r, data.indexOfDestinationCc );
}
String mailDestinationBCc = null;
if ( data.indexOfDestinationBCc > -1 ) {
mailDestinationBCc = data.previousRowMeta.getString( r, data.indexOfDestinationBCc );
}
String mailSenderName = null;
if ( data.indexOfSenderName > -1 ) {
mailSenderName = data.previousRowMeta.getString( r, data.indexOfSenderName );
}
String mailSenderAddress = data.previousRowMeta.getString( r, data.indexOfSenderAddress );
// reply addresses
String mailReplyToAddresses = null;View on GitHub (pinned to f3058517a1)