pentaho/pentaho-kettle · error · KettleException

SynchronizeAfterMerge.Log.OperationFieldEmpty

SynchronizeAfterMerge.Log.OperationFieldEmpty

Error message

SynchronizeAfterMerge.Log.OperationFieldEmpty

What it means

Thrown in lookupValues() when the 'operation' field value (from the configured OperationOrderField) is null on the incoming row. The SynchronizeAfterMerge step needs a non-null operation marker ('insert', 'update', or 'delete' sentinel values) to decide what SQL to run against the target table. If the field is absent or null on the row, the step cannot classify the row and aborts.

Solutions

  1. Fix the upstream data so the operation field is never null (e.g. COALESCE(op,'insert') in the SQL or an 'If field value is null' step before this step).
  2. Verify the 'Operation order field' setting in the step dialog points to the actual field carrying insert/update/delete markers.
  3. Add a Filter rows step to route rows with a null operation field to an error stream instead of into this step.
  4. If operation values come from a variable/parameter mapping, check the variable is defined so the field is populated.

Example fix

// before (SQL feeding the step)
SELECT id, op FROM staging;
// after
SELECT id, COALESCE(op, 'insert') AS op FROM staging;
Defensive patterns

Strategy: validation

Validate before calling

// Before the step: reject rows with null operation field
if (getFieldValue(row, "operation") == null) {
  throw new ValidationException("operation field is null for row: " + row);
}
// or in SQL: SELECT COALESCE(operation, 'insert') AS operation FROM staging

Try / catch

catch (KettleException e) {
  if (e.getMessage().contains("OperationFieldEmpty")) {
    logError("Operation field is null; fix upstream data or mapping.");
  }
  throw e;
}

Prevention

When it happens

Trigger: processRow calls lookupValues() per input row; operation = row value at the index of meta.getOperationOrderField(). It is null when the input stream's operation field contains a null value, or when the field exists in the dialog config but the upstream step emits null for that row.

Common situations: Upstream table input / lookup returns nulls for the operation column; user configured the wrong operation field name so a wrong (null-typed) column is picked; generated rows omit the operation field for some rows; joins produce null operation values for unmatched records.

Related errors


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

Appendix: source

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

    // do we insert, update or delete ?
    String operation = data.inputRowMeta.getString( row, data.indexOfOperationOrderField );

    boolean rowIsSafe = false;
    boolean sendToErrorRow = false;
    String errorMessage = null;
    int[] updateCounts = null;
    List<Exception> exceptionsList = null;
    boolean batchProblem = false;

    data.lookupFailure = false;
    boolean performInsert = false;
    boolean performUpdate = false;
    boolean performDelete = false;
    boolean lineSkipped = false;

    try {
      if ( operation == null ) {
        throw new KettleException( BaseMessages.getString( PKG, "SynchronizeAfterMerge.Log.OperationFieldEmpty", meta
          .getOperationOrderField() ) );
      }

      if ( meta.istablenameInField() ) {
        // get dynamic table name
        data.realTableName = data.inputRowMeta.getString( row, data.indexOfTableNameField );
        if ( Utils.isEmpty( data.realTableName ) ) {
          throw new KettleStepException( "The name of the table is not specified!" );
        }
        data.realSchemaTable =
          data.db.getDatabaseMeta().getQuotedSchemaTableCombination( data.realSchemaName, data.realTableName );
      }

      if ( operation.equals( data.insertValue ) ) {
        // directly insert data into table
        /*
         *
         * INSERT ROW

View on GitHub (pinned to f3058517a1)