pentaho/pentaho-kettle · error · KettleException

SalesforceDelete.Error.WriteToSalesforce

Error message

SalesforceDelete.Error.WriteToSalesforce

What it means

writeToSalesForce catches any exception raised while sending buffered rows to Salesforce and rethrows it as a KettleException with this message including the underlying error text. It signals that the write/delete operation against Salesforce failed during execution of the step.

Solutions

  1. Read the embedded message for the underlying Salesforce error (e.g. INVALID_SESSION_ID, MALFORMED_ID)
  2. Re-authenticate / refresh the Salesforce connection if the session expired
  3. Validate that all input ID values are well-formed 15/18-char Salesforce IDs
  4. Reduce the batch size in the step settings and retry if limits or timeouts are involved

Example fix

// before: IDs from upstream may be malformed
row[0] = someFreeTextField;
// after: validate ID format before writing to the delete step
if (!(someFreeTextField instanceof String) || !((String) someFreeTextField).matches("[a-zA-Z0-9]{15}([a-zA-Z0-9]{3})?")) {
  throw new KettleException("Invalid Salesforce ID: " + someFreeTextField);
}
row[0] = someFreeTextField;
Defensive patterns

Strategy: try-catch

Validate before calling

// validate IDs before they reach the delete step
for (Object id : idColumn) {
  if (!(id instanceof String) || !((String) id).matches("[a-zA-Z0-9]{15}([a-zA-Z0-9]{3})?")) {
    throw new IllegalArgumentException("Invalid Salesforce ID: " + id);
  }
}

Type guard

boolean isValidSalesforceId(Object o) {
  return o instanceof String && ((String) o).matches("[a-zA-Z0-9]{15}([a-zA-Z0-9]{3})?");
}

Try / catch

try {
  writeToSalesForce(rowData);
} catch (KettleException e) {
  logError("Salesforce write failed: " + e.getMessage());
  if (e.getMessage().contains("INVALID_SESSION_ID")) {
    connection.reconnect();
  }
  throw e;
}

Prevention

When it happens

Trigger: Any failure inside the write path: building/sending the delete call, flushing buffers (flushBuffers), or Salesforce returning an error response while processing the batch.

Common situations: Invalid or expired Salesforce session; batch containing malformed IDs; Salesforce API limits hit mid-transformation; network failure while calling the SOAP API.

Related errors


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

Appendix: source

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

      }

      // if there is room in the buffer
      if ( data.iBufferPos < meta.getBatchSizeInt() ) {

        // Load the buffer array
        data.deleteId[data.iBufferPos] = getInputRowMeta().getString( rowData, data.indexOfKeyField );
        data.outputBuffer[data.iBufferPos] = rowData;
        data.iBufferPos++;
      }

      if ( data.iBufferPos >= meta.getBatchSizeInt() ) {
        if ( log.isDetailed() ) {
          logDetailed( BaseMessages.getString( PKG, "SalesforceDelete.Log.CallingFlush" ) );
        }
        flushBuffers();
      }
    } catch ( Exception e ) {
      throw new KettleException( BaseMessages.getString( PKG, "SalesforceDelete.Error.WriteToSalesforce", e
        .getMessage() ) );
    }
  }

  private void flushBuffers() throws KettleException {

    try {
      if ( data.deleteId.length > data.iBufferPos ) {
        String[] smallBuffer = new String[data.iBufferPos];
        System.arraycopy( data.deleteId, 0, smallBuffer, 0, data.iBufferPos );
        data.deleteId = smallBuffer;
      }
      // delete the object(s) by sending the array to the web service
      data.deleteResult = data.connection.delete( data.deleteId );
      int nr = data.deleteResult.length;
      for ( int j = 0; j < nr; j++ ) {
        if ( data.deleteResult[j].isSuccess() ) {

View on GitHub (pinned to f3058517a1)