pentaho/pentaho-kettle · error · KettleException

Mail.Exception.CouldnotFindAttachedContentField

Error message

Mail.Exception.CouldnotFindAttachedContentField

What it means

'Attach content from field' is enabled and a content field name was configured, but no field with that name exists in the incoming row. cacheFieldsPosition throws this KettleException because indexOfValue returned -1 for meta.getAttachContentField().

Solutions

  1. Verify the 'Content field' name in the attachment settings exactly matches a field in the input stream.
  2. Preview upstream rows to confirm the content field reaches the Mail step.
  3. Disable 'Attach content from field' if attachments should come from files.

Example fix

// before
// attachContentField = "content" but stream field is "file_content"
// after
// meta.setAttachContentField("file_content");
Defensive patterns

Strategy: validation

Validate before calling

if (meta.isAttachContentFromField()
    && meta.getAttachContentField() != null && !meta.getAttachContentField().isEmpty()
    && rowMeta.indexOfValue(meta.getAttachContentField()) < 0) {
  throw new KettleException("Attached content field not found: " + meta.getAttachContentField());
}

Try / catch

try { sendMail(); } catch (KettleException e) { if (e.getMessage().contains("CouldnotFindAttachedContentField")) { logError("Content field name does not match any input stream field"); } throw e; }

Prevention

When it happens

Trigger: meta.isAttachContentFromField() is true, the configured attachContentField is non-empty, and data.previousRowMeta.indexOfValue(attachedContentField) < 0.

Common situations: Typo in the content field name; upstream step that produced the content field removed; field renamed during transformation refactor.

Related errors


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

Appendix: source

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

        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 ) );
      }
    } else {

      // Dynamic Zipfilename
      if ( meta.isZipFilenameDynamic() ) {

View on GitHub (pinned to f3058517a1)