pentaho/pentaho-kettle · error · KettleException

SalesforceInput.ErrorDelete

Error message

SalesforceInput.ErrorDelete

What it means

KettleException thrown by SalesforceConnection.delete() when the SOAP delete() call fails. The exception text is embedded in the message. It wraps transport-level failures of binding.delete(id) for the given record Id array.

Solutions

  1. Read the embedded Salesforce fault to see which Ids failed and why
  2. Validate all Ids are non-null, well-formed 15/18-char Salesforce Ids before calling delete
  3. Check Delete object permission for the integration user
  4. Skip already-deleted records (query existence first or treat ENTITY_IS_DELETED as success)
  5. Verify session validity / reconnect before retrying

Example fix

// before
connection.delete(ids); // ids may contain nulls from upstream
// after
String[] valid = Arrays.stream(ids).filter(i -> i != null && i.matches("[a-zA-Z0-9]{15,18}")).toArray(String[]::new);
if (valid.length > 0) connection.delete(valid);
Defensive patterns

Strategy: validation

Validate before calling

boolean deletable = id != null && id.length > 0 && Arrays.stream(id).allMatch(i -> i != null && i.matches("[a-zA-Z0-9]{15,18}")); if (!deletable) throw new IllegalArgumentException("delete() requires a non-empty array of valid Salesforce Ids");

Type guard

boolean validIds(String[] ids) { return ids != null && ids.length > 0 && Arrays.stream(ids).allMatch(i -> i != null && i.length() >= 15); }

Try / catch

try { results = connection.delete(id); } catch (KettleException e) { log.logError("Delete failed: " + e.getMessage(), e); throw e; } // fault text is in e.getMessage()

Prevention

When it happens

Trigger: Calling delete(id) when the binding's delete() throws: invalid/empty Id array, invalid session, or permission failure on the object being deleted.

Common situations: Deleting records already deleted or belonging to another user without delete rights (INVALID_CROSS_REFERENCE_KEY), empty or malformed Ids passed from upstream rows, API user lacking Delete permission.

Related errors


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

Appendix: source

Thrown at plugins/salesforce/core/src/main/java/org/pentaho/di/trans/steps/salesforce/SalesforceConnection.java:893

      return getBinding().create( normalizedSfBuffer.toArray( new SObject[normalizedSfBuffer.size()] ) );
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "SalesforceInput.ErrorInsert", e ) );
    }
  }

  public SaveResult[] update( SObject[] sfBuffer ) throws KettleException {
    try {
      return getBinding().update( sfBuffer );
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "SalesforceInput.ErrorUpdate", e ) );
    }
  }

  public DeleteResult[] delete( String[] id ) throws KettleException {
    try {
      return getBinding().delete( id );
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "SalesforceInput.ErrorDelete", e ) );
    }
  }

  public static XmlObject createMessageElement( String name, Object value, boolean useExternalKey ) throws Exception {

    XmlObject me = null;

    if ( useExternalKey ) {
      // We use an external key
      // the structure should be like this :
      // object:externalId/lookupField
      // where
      // object is the type of the object
      // externalId is the name of the field in the object to resolve the value
      // lookupField is the name of the field in the current object to update (is the "__r" version)

      int indexOfType = name.indexOf( ":" );
      if ( indexOfType > 0 ) {

View on GitHub (pinned to f3058517a1)