pentaho/pentaho-kettle · error · KettleException

SalesforceDelete.Error.CanNotFindFDeleteKeyField

Error message

SalesforceDelete.Error.CanNotFindFDeleteKeyField

What it means

After resolving the configured delete key field name, processRow looks it up in the incoming row stream via getInputRowMeta().indexOfValue(). This error is thrown when the field name is configured but is not present in the input rows, so the step cannot locate the Salesforce record IDs to delete.

Solutions

  1. Ensure the upstream step actually emits the configured key field (check with a preview/Get Fields)
  2. Correct the 'Key field' name in the Delete step dialog to exactly match the stream field name (case and spelling)
  3. Insert or repair a Select Values / Field renamer step so the ID field reaches the Delete step with the expected name
  4. Trim whitespace from the configured field name

Example fix

// before: configured name does not exist in the stream
meta.setDeleteField("ID ");
// after: exact match with the field produced upstream
meta.setDeleteField("Id");
Defensive patterns

Strategy: validation

Validate before calling

// before the Delete step, assert the field exists in the stream
RowMetaInterface inputFields = transMeta.getPrevStepFields(stepName);
if (inputFields.indexOfValue(realFieldName) < 0) {
  throw new IllegalStateException("Field '" + realFieldName + "' not found in input stream of Salesforce Delete step");
}

Try / catch

try {
  executeTransformation();
} catch (KettleException e) {
  if (e.getMessage().contains("CanNotFindFDeleteKeyField")) {
    logError("Key field missing from input rows; check upstream field names: " + e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: The delete key field name (after variable substitution) does not exactly match any field in the input row metadata — wrong name, wrong case, or the upstream step no longer produces the field.

Common situations: Renaming an upstream field without updating the Delete step; extra spaces in the configured field name; the field is only available after a Select Values step that was removed; case-sensitive mismatch between configured name and stream field.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at plugins/salesforce/core/src/main/java/org/pentaho/di/trans/steps/salesforcedelete/SalesforceDelete.java:82

      data.deleteId = new String[meta.getBatchSizeInt()];
      data.outputBuffer = new Object[meta.getBatchSizeInt()][];

      // Create the output row meta-data
      data.outputRowMeta = getInputRowMeta().clone();
      meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
                      metaStore );

      // Check deleteKeyField
      String realFieldName = environmentSubstitute( meta.getDeleteField() );
      if ( Utils.isEmpty( realFieldName ) ) {
        throw new KettleException( BaseMessages.getString( PKG, "SalesforceDelete.Error.DeleteKeyFieldMissing" ) );
      }

      // return the index of the field in the input stream
      data.indexOfKeyField = getInputRowMeta().indexOfValue( realFieldName );
      if ( data.indexOfKeyField < 0 ) {
        // the field is unreachable!
        throw new KettleException( BaseMessages.getString(
          PKG, "SalesforceDelete.Error.CanNotFindFDeleteKeyField", realFieldName ) );
      }
    }

    try {
      writeToSalesForce( outputRowData );
    } catch ( Exception e ) {
      throw new KettleStepException( BaseMessages.getString( PKG, "SalesforceDelete.log.Exception" ), e );
    }
    return true;
  }

  private void writeToSalesForce( Object[] rowData ) throws KettleException {
    try {

      if ( log.isDetailed() ) {
        logDetailed( BaseMessages.getString( PKG, "SalesforceDelete.Log.WriteToSalesforce", data.iBufferPos, meta
          .getBatchSizeInt() ) );

View on GitHub (pinned to f3058517a1)