pentaho/pentaho-kettle · error · KettleException

Mail.Exception.AttachedContentFieldEmpty

Error message

Mail.Exception.AttachedContentFieldEmpty

What it means

'Attach content from field' is enabled in the Mail step, which means email attachments come from row data rather than physical files, but the 'attached content field' setting is empty. The step refuses to continue because it cannot know which field holds the attachment content.

Solutions

  1. Open the Mail step, go to the attachment settings, and set the 'Content field' to the name of the field holding the attachment content.
  2. If attachments should come from files instead, disable 'Attach content from field'.
  3. Ensure an upstream step actually produces the content field.

Example fix

// before
// isAttachContentFromField = true, attachContentField = ""
// after
// meta.setAttachContentField("file_content"); // field produced upstream
Defensive patterns

Strategy: validation

Validate before calling

if (meta.isAttachContentFromField()
    && (meta.getAttachContentField() == null || meta.getAttachContentField().isEmpty())) {
  throw new KettleException("'Attach content from field' is enabled but no content field is configured");
}

Try / catch

try { sendMail(); } catch (KettleException e) { if (e.getMessage().contains("AttachedContentFieldEmpty")) { logError("Set the attached-content field name in the Mail step attachment settings"); } throw e; }

Prevention

When it happens

Trigger: meta.isAttachContentFromField() is true and Utils.isEmpty(meta.getAttachContentField()) — the 'Content field' name in the attachment section was never filled in.

Common situations: Enabling the 'attach content from field' checkbox but forgetting to specify which field carries the content; step migration/import losing the field setting.

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

Appendix: source

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

    if ( !Utils.isEmpty( meta.getComment() ) ) {
      // cache the position of the comment field
      if ( data.indexOfComment < 0 ) {
        String realComment = meta.getComment();
        data.indexOfComment = data.previousRowMeta.indexOfValue( realComment );
        if ( data.indexOfComment < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindCommentField", realComment ) );
        }
      }
    }

    if ( meta.isAttachContentFromField() ) {
      // We are dealing with file content directly loaded from file
      // and not physical file
      String attachedContentField = meta.getAttachContentField();
      if ( Utils.isEmpty( attachedContentField ) ) {
        // Empty Field
        throw new KettleException( BaseMessages.getString( PKG, "Mail.Exception.AttachedContentFieldEmpty" ) );
      }
      data.indexOfAttachedContent = data.previousRowMeta.indexOfValue( attachedContentField );
      if ( data.indexOfAttachedContent < 0 ) {
        throw new KettleException( BaseMessages.getString(
          PKG, "Mail.Exception.CouldnotFindAttachedContentField", attachedContentField ) );
      }
      // Attached content filename
      String attachedContentFileNameField = meta.getAttachContentFileNameField();
      if ( Utils.isEmpty( attachedContentFileNameField ) ) {
        // Empty Field
        throw new KettleException( BaseMessages.getString(
          PKG, "Mail.Exception.AttachedContentFileNameFieldEmpty" ) );
      }
      data.IndexOfAttachedFilename = data.previousRowMeta.indexOfValue( attachedContentFileNameField );
      if ( data.IndexOfAttachedFilename < 0 ) {
        throw new KettleException( BaseMessages.getString(
          PKG, "Mail.Exception.CouldnotFindAttachedContentFileNameField", attachedContentFileNameField ) );
      }

View on GitHub (pinned to f3058517a1)