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
- Check the chained cause for the underlying Salesforce/transport error.
- Enable error handling on the step to route failed batches to an error stream instead of aborting.
- Reconnect/re-authenticate to Salesforce and re-run the transformation.
- 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
- Enable error handling on the step to avoid whole-transformation aborts
- Use correct API endpoint URLs for your Salesforce instance
- Batch records in moderate sizes to limit transient failure impact
- Schedule around Salesforce maintenance windows
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
- SalesforceUpsert.Error.FlushBuffer
- SalesforceUpsert.FailedInWrite
- SalesforceUpsertDialog.FieldsMissing.DialogMessage
- SalesforceConnection.UnableToFindObjectType
- SalesforceUpdateMeta.Exception.ErrorReadingRepository
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)