pentaho/pentaho-kettle · error · KettleStepException

SynchronizeAfterMerge.Exception.FieldRequired…

Error message

SynchronizeAfterMerge.Exception.FieldRequired (updateStream[i])

What it means

The step resolves each 'Update stream' field (the stream-side field whose value is written to the table) to an index in the input row. If updateStream[i] is not present in the incoming RowMeta, processRow() throws KettleStepException FieldRequired(updateStream[i]). This guards against writing from a nonexistent field during INSERT/UPDATE generation.

Solutions

  1. Re-open the step and re-pick each 'Update stream' field from the field dropdown so names match the incoming stream
  2. Add a 'Select values' rename step upstream to recreate the expected field name
  3. Verify with preview on the previous step that the field is still produced at runtime
  4. Check for trailing whitespace or case mismatches in manually typed field names

Example fix

// before
updateStream: total_amt (upstream now emits total_amount) -> indexOfValue = -1 -> throw
// after
updateStream: total_amount
// or upstream Select values: rename total_amount -> total_amt
Defensive patterns

Strategy: validation

Validate before calling

var m = stepMeta.getStepMetaInterface();
var prev = transMeta.getPrevStepFields(stepMeta);
for (var i = 0; i < m.getUpdateStream().length; i++) {
  if (prev.indexOfValue(m.getUpdateStream()[i]) < 0) throw new Error("Update stream field missing: " + m.getUpdateStream()[i]);
}

Type guard

function allFieldsExist(names, rowMeta) { return names.every(function(n) { return rowMeta.indexOfValue(n) >= 0; }); }

Try / catch

try { trans.execute(...); } catch (KettleException e) { if (e.getMessage().contains("FieldRequired")) { log.error("Update stream field missing: " + e.getMessage()); } else throw e; }

Prevention

When it happens

Trigger: A field named in the 'Update stream' column of the mapping grid is missing from the input stream: renamed/deleted upstream, wrong casing, or the step was moved behind a filter/select that dropped the field.

Common situations: Schema drift between environments; removing a calculated field upstream after the mapping was configured; typo when typing field names manually into the grid instead of picking from the dropdown.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/synchronizeaftermerge/SynchronizeAfterMerge.java:750

        ValueMetaInterface insValue = data.insertRowMeta.searchValueMeta( meta.getUpdateLookup()[i] );
        if ( insValue == null ) { // Don't add twice!
          // we already checked that this value exists so it's probably safe to ignore lookup failure...
          ValueMetaInterface insertValue = data.inputRowMeta.searchValueMeta( meta.getUpdateStream()[i] ).clone();
          insertValue.setName( meta.getUpdateLookup()[i] );
          data.insertRowMeta.addValueMeta( insertValue );
        } else {
          throw new KettleStepException( BaseMessages.getString( PKG,
            "SynchronizeAfterMerge.Error.SameColumnInsertedTwice", insValue.getName() ) );
        }
      }

      // Cache the position of the compare fields in Row row
      //
      data.valuenrs = new int[meta.getUpdateLookup().length];
      for (int i = 0; i < meta.getUpdateLookup().length; i++) {
        data.valuenrs[i] = data.inputRowMeta.indexOfValue( meta.getUpdateStream()[i] );
        if ( data.valuenrs[i] < 0 ) { // couldn't find field!
          throw new KettleStepException( BaseMessages.getString( PKG, "SynchronizeAfterMerge.Exception.FieldRequired",
            meta.getUpdateStream()[i] ) );
        }
        if ( log.isDebug() ) {
          logDebug( BaseMessages.getString( PKG, "SynchronizeAfterMerge.Log.FieldHasDataNumbers", meta
            .getUpdateStream()[i] ) + data.valuenrs[i] );
        }
      }

      if ( !meta.istablenameInField() ) {
        // Prepare Lookup statement
        if ( meta.isPerformLookup() ) {
          data.lookupStatement = data.preparedStatements.get( data.realSchemaTable + "lookup" );
          if ( data.lookupStatement == null ) {
            String sql = getLookupStatement( data.inputRowMeta );
            if ( log.isDebug() ) {
              logDebug( "Preparation of the lookup SQL statement : " + sql );
            }

View on GitHub (pinned to f3058517a1)