pentaho/pentaho-kettle · error · KettleException

SalesforceDelete.Error.DeleteKeyFieldMissing

Error message

SalesforceDelete.Error.DeleteKeyFieldMissing

What it means

SalesforceDelete.processRow validates that the step's delete key field is configured before deleting records from Salesforce. If the 'DeleteField' setting is empty or resolves to an empty string after variable substitution, the step cannot know which input field contains the record IDs to delete, so it aborts with this KettleException.

Solutions

  1. Open the Salesforce Delete step dialog and set the 'Key field' property to the input field containing the IDs
  2. Verify the variable used in the field setting is actually defined in the runtime environment (kettle.properties, parameters)
  3. Re-save the transformation to ensure the DeleteField attribute is persisted
  4. Add a check in the transformation's initialization (or a Get Variables step) to validate the variable resolves to a non-empty value

Example fix

// before: step meta with empty delete field
meta.setDeleteField("");
// after
meta.setDeleteField("Id"); // or "${SF_DELETE_KEY_FIELD}" with the variable defined in kettle.properties
Defensive patterns

Strategy: validation

Validate before calling

// before executing the transformation
String realFieldName = environmentSubstitute(meta.getDeleteField());
if (realFieldName == null || realFieldName.trim().isEmpty()) {
  throw new IllegalStateException("Salesforce Delete step: key field (DeleteField) is not set");
}

Try / catch

try {
  executeTransformation();
} catch (KettleException e) {
  if (e.getMessage().contains("DeleteKeyFieldMissing")) {
    logError("Configure the Salesforce Delete step's 'Key field' before running");
  }
  throw e;
}

Prevention

When it happens

Trigger: Running a Salesforce Delete transformation step whose 'Key field' (deleteField) property is blank, or contains only a variable reference that resolves to empty at runtime.

Common situations: A transformation copied or re-created without filling in the key field; environment variable not defined so environmentSubstitute returns empty; step exported/imported without the field persisted.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

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

      return false;
    }

    // If we haven't looked at a row before then do some basic setup.
    if ( first ) {
      first = false;

      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;
  }

View on GitHub (pinned to f3058517a1)