pentaho/pentaho-kettle · error · KettleException

SalesforceUpsert.FailedUpsert

Error message

SalesforceUpsert.FailedUpsert

What it means

Thrown in SalesforceUpsert.flushBuffers when the whole upsert call itself throws (transport/login/SOAP failure) and the step is NOT configured for error handling. Non-Kettle exceptions are wrapped with this message including e.getMessage(); KettleExceptions are rethrown unchanged. If error handling is enabled, the row goes to the error stream instead.

Solutions

  1. Check the chained cause for the underlying Salesforce/transport error.
  2. Enable error handling on the step to route failed batches to an error stream instead of aborting.
  3. Reconnect/re-authenticate to Salesforce and re-run the transformation.
  4. Add retry logic or split large batches to reduce exposure to transient failures.

Example fix

// before: no error handling configured
// transformation aborts on transient Salesforce outage
// after: in the step dialog, enable error handling and set an error target step
stepMeta.setSupportsErrorHandling(true); // or check 'Error handling' in the UI
Defensive patterns

Strategy: retry

Validate before calling

// confirm session/endpoint health before batch upserts
if (!salesforceConnection.isLoggedIn()) salesforceConnection.login(username, password + securityToken);

Try / catch

try { writeToSalesForce(rowData); } catch (KettleException e) { if (isTransient(e)) { backoffRetry(rowData); } else throw e; }

Prevention

When it happens

Trigger: The Salesforce upsert SOAP call throws — invalid session, connection failure, endpoint timeout, WS client error — while getStepMeta().isDoingErrorHandling() is false.

Common situations: Salesforce session expired mid-transformation; network/firewall interruption; wrong API endpoint for the Salesforce instance; Salesforce service outage during a long run.

Related errors


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

Appendix: source

Thrown at plugins/salesforce/core/src/main/java/org/pentaho/di/trans/steps/salesforceupsert/SalesforceUpsert.java:289

            logDebug( BaseMessages.getString( PKG, "SalesforceUpsert.PassingRowToErrorStep" ) );
          }
          putError( getInputRowMeta(), data.outputBuffer[j], 1, errorMessage, null, "SalesforceUpsert001" );
        }

      }

      // reset the buffers
      data.sfBuffer = new SObject[meta.getBatchSizeInt()];
      data.outputBuffer = new Object[meta.getBatchSizeInt()][];
      data.iBufferPos = 0;

    } catch ( Exception e ) {
      if ( !getStepMeta().isDoingErrorHandling() ) {
        if ( e instanceof KettleException ) {
          // I know, bad form usually. But I didn't want to duplicate the logic with a catch(KettleException). MB
          throw (KettleException) e;
        } else {
          throw new KettleException(
            BaseMessages.getString( PKG, "SalesforceUpsert.FailedUpsert", e.getMessage() ), e );
        }
      }
      // Simply add this row to the error row
      if ( log.isDebug() ) {
        logDebug( "Passing row to error step" );
      }

      for ( int i = 0; i < data.iBufferPos; i++ ) {
        putError( data.inputRowMeta, data.outputBuffer[i], 1, e.getMessage(), null, "SalesforceUpsert002" );
      }
    } finally {
      if ( data.upsertResult != null ) {
        data.upsertResult = null;
      }
    }

  }

View on GitHub (pinned to f3058517a1)