pentaho/pentaho-kettle · error · KettleException
SalesforceUpsertDialog.FieldsMissing.DialogMessage
Error message
SalesforceUpsertDialog.FieldsMissing.DialogMessage
What it means
Thrown in SalesforceUpsert.processRow when the step's update field mapping grid is empty — meta.getUpdateLookup().length is 0. An upsert step with nothing to update is treated as a configuration error and aborts the transformation rather than silently doing nothing.
Solutions
- Open the Salesforce Upsert step dialog and populate the 'Update fields' table (field to update + stream field).
- Verify the saved ktr contains the <updateLookup>/<updateStream> grid entries.
- Re-enter external-ID and field mappings if a version upgrade dropped the grid contents.
Example fix
// before (transformation XML)
<fields/>
// after
<fields>
<field>
<lookup>Name</lookup>
<stream>name</stream>
</field>
</fields> Defensive patterns
Strategy: validation
Validate before calling
if (meta.getUpdateLookup() == null || meta.getUpdateLookup().length == 0) {
throw new KettleException("Salesforce Upsert step has no update field mappings configured");
} Try / catch
try { return processRow(row); } catch (KettleException e) { if (e.getMessage().contains("FieldsMissing")) { log.error("Configure the update field grid in the step dialog"); } throw e; } Prevention
- Always fill the 'Update fields' grid before saving the step
- Review mappings when copying/template transformations
- Re-validate step configuration after manual ktr XML edits
When it happens
Trigger: Running a Salesforce Upsert step whose 'Update fields' table has zero rows: the user never opened/configured the step, or the grid was cleared after editing the ktr XML.
Common situations: Transformation copied from a template where the upsert mapping was never filled in; settings lost after XML/repository edit; grid accidentally emptied in the dialog and saved.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- SalesforceUpsert.Error.FlushBuffer
- SalesforceUpsert.FailedInWrite
- SalesforceUpsert.FailedUpsert
- AddSequence.Exception.NoSpecifiedMethod
- BaseStep.Exception.SourceStepToReadFromCantRunInMultipleCopies
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/5fdfaeb4f9361c83.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/salesforce/core/src/main/java/org/pentaho/di/trans/steps/salesforceupsert/SalesforceUpsert.java:89
flushBuffers();
}
setOutputDone();
return false;
}
// If we haven't looked at a row before then do some basic setup.
if ( first ) {
first = false;
data.sfBuffer = new SObject[meta.getBatchSizeInt()];
data.outputBuffer = new Object[meta.getBatchSizeInt()][];
// get total fields in the grid
data.nrfields = meta.getUpdateLookup().length;
// Check if field list is filled
if ( data.nrfields == 0 ) {
throw new KettleException( BaseMessages.getString(
PKG, "SalesforceUpsertDialog.FieldsMissing.DialogMessage" ) );
}
// Create the output row meta-data
data.inputRowMeta = getInputRowMeta().clone();
data.outputRowMeta = data.inputRowMeta.clone();
meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
metaStore );
// Build the mapping of input position to field name
data.fieldnrs = new int[meta.getUpdateStream().length];
for ( int i = 0; i < meta.getUpdateStream().length; i++ ) {
data.fieldnrs[i] = getInputRowMeta().indexOfValue( meta.getUpdateStream()[i] );
if ( data.fieldnrs[i] < 0 ) {
throw new KettleException( BaseMessages.getString( PKG, "SalesforceUpsert.FieldNotFound", meta
.getUpdateStream()[i] ) );
}
}View on GitHub (pinned to f3058517a1)