pentaho/pentaho-kettle · error · KettleException

Mail.Exception.CouldnotFindContactPersonField

Error message

Mail.Exception.CouldnotFindContactPersonField

What it means

Thrown by cacheFieldsPosition when the contact-person field configured in Mail meta is not present in the incoming row. Only checked when a contact-person field is configured; the -1 lookup result aborts the step before sending.

Solutions

  1. Fix the 'Contact Person fieldname' setting to an existing incoming column
  2. Add the column upstream with Select Values / Add constants
  3. Clear the contact-person setting if unused

Example fix

// before
meta.setContactPerson("contact_nm");
// after
meta.setContactPerson("contact_name");
Defensive patterns

Strategy: validation

Validate before calling

// ensure the contact-person field exists when configured
if (!isEmpty(meta.getContactPerson()) && rowMeta.indexOfValue(meta.getContactPerson()) < 0) {
  logError("Contact person field not in stream: " + meta.getContactPerson());
}

Try / catch

try {
  step.processRow();
} catch (KettleException e) {
  if (e.getMessage().contains("CouldnotFindContactPersonField")) {
    logError("Contact person field missing: " + e.getMessage());
  }
}

Prevention

When it happens

Trigger: meta.getContactPerson() is non-empty and data.indexOfContactPerson == -1 after indexOfValue on previousRowMeta.

Common situations: Contact-person column removed/renamed upstream; wrong field typed in the Mail step dialog; different input source used than when the step was configured.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

      // cache the position of the reply to field
      if ( data.indexOfReplyToAddresses < 0 ) {
        String realReplyToAddresses = meta.getReplyToAddresses();
        data.indexOfReplyToAddresses = data.previousRowMeta.indexOfValue( realReplyToAddresses );
        if ( data.indexOfReplyToAddresses < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindReplyToAddressesField", realReplyToAddresses ) );
        }
      }
    }

    // Contact Person
    if ( !Utils.isEmpty( meta.getContactPerson() ) ) {
      // cache the position of the destination field
      if ( data.indexOfContactPerson < 0 ) {
        String realContactPerson = meta.getContactPerson();
        data.indexOfContactPerson = data.previousRowMeta.indexOfValue( realContactPerson );
        if ( data.indexOfContactPerson < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindContactPersonField", realContactPerson ) );
        }
      }
    }
    // Contact Phone
    if ( !Utils.isEmpty( meta.getContactPhone() ) ) {
      // cache the position of the destination field
      if ( data.indexOfContactPhone < 0 ) {
        String realContactPhone = meta.getContactPhone();
        data.indexOfContactPhone = data.previousRowMeta.indexOfValue( realContactPhone );
        if ( data.indexOfContactPhone < 0 ) {
          throw new KettleException( BaseMessages.getString(
            PKG, "Mail.Exception.CouldnotFindContactPhoneField", realContactPhone ) );
        }
      }
    }
    // cache the position of the Server field
    if ( data.indexOfServer < 0 ) {

View on GitHub (pinned to f3058517a1)