pentaho/pentaho-kettle · error · KettleException

Mail.Exception.CouldnotFindSubjectField

Error message

Mail.Exception.CouldnotFindSubjectField

What it means

The Mail step is configured to take the mail subject from a field, but the configured subject field name was not found in the incoming row's metadata. cacheFieldsPosition throws this KettleException when the indexOfValue lookup returns -1.

Solutions

  1. Verify the 'Subject' setting holds a field name that exists in the input stream, exactly.
  2. If the subject is static text, clear the Subject field and supply the subject via a static subject setting or an upstream step.
  3. Preview the input rows to confirm the subject-producing field is present.

Example fix

// before
// Subject field: "Monthly Report" (literal text, not a field)
// after
// Add upstream step producing field "mail_subject" with value 'Monthly Report',
// then set the Subject field to "mail_subject"
Defensive patterns

Strategy: validation

Validate before calling

if (meta.getSubject() != null && !meta.getSubject().isEmpty()
    && rowMeta.indexOfValue(meta.getSubject()) < 0) {
  throw new KettleException("Subject field not found in input stream: " + meta.getSubject());
}

Try / catch

try { sendMail(); } catch (KettleException e) { if (e.getMessage().contains("CouldnotFindSubjectField")) { logError("Subject setting must reference an existing stream field"); } throw e; }

Prevention

When it happens

Trigger: meta.getSubject() is non-empty (treated as a field name) and data.previousRowMeta has no field with that exact name.

Common situations: Developer typed the subject text directly into the subject field setting (which expects a field name); upstream column renamed; case mismatch.

Related errors


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

Appendix: source

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

    // cache the position of the Authentication user field
    if ( meta.isUsingAuthentication().equals( MailMeta.AUTENTICATION_BASIC ) || meta.isUsingAuthentication().equals( MailMeta.AUTENTICATION_OAUTH ) ) {
      if ( data.indexOfAuthenticationUser < 0 ) {
        String realAuthenticationUser = meta.getAuthenticationUser();
        data.indexOfAuthenticationUser = data.previousRowMeta.indexOfValue( realAuthenticationUser );
        if ( data.indexOfAuthenticationUser < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindAuthenticationUserField", realAuthenticationUser ) );
        }
      }
    }
    // Mail Subject
    if ( !Utils.isEmpty( meta.getSubject() ) ) {
      // cache the position of the subject field
      if ( data.indexOfSubject < 0 ) {
        String realSubject = meta.getSubject();
        data.indexOfSubject = data.previousRowMeta.indexOfValue( realSubject );
        if ( data.indexOfSubject < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindSubjectField", realSubject ) );
        }
      }
    }
    // Mail Comment
    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() ) {

View on GitHub (pinned to f3058517a1)