pentaho/pentaho-kettle · error · KettleException

Failed in writeToSalesForce:

Error message

Failed in writeToSalesForce: 

What it means

writeToSalesForce() wraps its buffer management and flush logic in a try/catch and rethrows as KettleException('\\nFailed in writeToSalesForce: ' + e.getMessage()). It aggregates any failure while preparing or flushing the Salesforce update batch. Note it keeps only e.getMessage(), so the exception class and stack are lost — a known debugging pain point.

Solutions

  1. Read the appended message after 'Failed in writeToSalesForce:' for the root Salesforce error text.
  2. Check step log output at detailed level for the specific SObject row being written.
  3. Validate field values/types sent to Salesforce (nulls, external-ID fields) — see errors 3747/3748 for the underlying flush failures.
  4. If diagnostics are unclear, enable detailed logging or patch the catch to pass the whole exception as cause.

Example fix

// before: cause and stacktrace are dropped
throw new KettleException( "\nFailed in writeToSalesForce: " + e.getMessage() );
// after: keep the cause for diagnosis
throw new KettleException( "\nFailed in writeToSalesForce", e );
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity-check batchSize and field data before executing the step
if (meta.getBatchSizeInt() <= 0 || meta.getBatchSizeInt() > 10000) {
  throw new IllegalArgumentException("Invalid batchSize: " + meta.getBatchSizeInt());
}

Try / catch

try {
  step.processRow();
} catch (KettleException e) {
  // message is 'Failed in writeToSalesForce: <root msg>' — parse and also check step logs
  log.error("writeToSalesForce failure: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Called from processRow per row (and from unit tests): exceptions while adding an SObject to the buffer or calling flushBuffers() — Salesforce API errors, connection failures, or internal NPEs.

Common situations: Batch update failing because of Salesforce API limits or bad field data; session timeout mid-batch; misconfigured batchSize leading to oversized requests.

Related errors


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

Appendix: source

Thrown at plugins/salesforce/core/src/main/java/org/pentaho/di/trans/steps/salesforceupdate/SalesforceUpdate.java:166

        if ( fieldsToNull.size() > 0 ) {
          // Set Null to fields
          sobjPass.setFieldsToNull( fieldsToNull.toArray( new String[fieldsToNull.size()] ) );
        }

        // Load the buffer array
        data.sfBuffer[data.iBufferPos] = sobjPass;
        data.outputBuffer[data.iBufferPos] = rowData;
        data.iBufferPos++;
      }

      if ( data.iBufferPos >= meta.getBatchSizeInt() ) {
        if ( log.isDetailed() ) {
          logDetailed( "Calling flush buffer from writeToSalesForce" );
        }
        flushBuffers();
      }
    } catch ( Exception e ) {
      throw new KettleException( "\nFailed in writeToSalesForce: " + e.getMessage() );
    }
  }

  private void flushBuffers() throws KettleException {

    try {
      if ( data.sfBuffer.length > data.iBufferPos ) {
        SObject[] smallBuffer = new SObject[data.iBufferPos];
        System.arraycopy( data.sfBuffer, 0, smallBuffer, 0, data.iBufferPos );
        data.sfBuffer = smallBuffer;
      }
      // update the object(s) by sending the array to the web service
      data.saveResult = data.connection.update( data.sfBuffer );
      int nr = data.saveResult.length;
      for ( int j = 0; j < nr; j++ ) {
        if ( data.saveResult[j].isSuccess() ) {
          // Row was updated
          String id = data.saveResult[j].getId();

View on GitHub (pinned to f3058517a1)