pentaho/pentaho-kettle · error · KettleStepException

Couldn't find field ' ' in row!

Error message

Couldn't find field '{0}' in row!

What it means

The Set Value Field step failed to locate one of the configured field names in the incoming row's metadata. During processRow it calls outputRowMeta.indexOfValue(fieldName); a negative index means the field does not exist in the row stream, so the step cannot know where to write the replacement value and throws KettleStepException. This is almost always a transformation design/configuration mismatch rather than a runtime data problem.

Solutions

  1. Open the Set Value Field step dialog and re-select the 'Field' entry so it matches an actual field in the incoming stream (use 'Get Fields').
  2. Verify the upstream step that produces the field actually runs before Set Value Field and outputs it; preview the previous step to see the real row fields.
  3. If the field name uses ${VARIABLE} substitution, log environmentSubstitute output or hardcode the name to confirm the variable resolves to the expected field.
  4. If the field is optional by design, restructure the flow (e.g. use a User Defined Java Expression or Filter so the step only runs when the field exists).

Example fix

// before (field typed manually, may not exist)
fieldName = "custmer_id";
// after (use exact upstream field name)
fieldName = "customer_id";
Defensive patterns

Strategy: validation

Validate before calling

// Before running, verify all configured fields exist in the incoming row meta
for (String name : meta.getFieldName()) {
  String resolved = environmentSubstitute(name);
  if (transMeta.getPrevStepFields(stepMeta).indexOfValue(resolved) < 0) {
    throw new IllegalStateException("Field not in row stream: " + resolved);
  }
}

Type guard

if (rowMeta.indexOfValue(fieldName) < 0) { return null; } // treat as absent field

Try / catch

try {
  trans.execute(null);
} catch (KettleStepException e) {
  log.error("Set Value Field misconfigured: {}", e.getMessage()); // fix step field mapping
}

Prevention

When it happens

Trigger: processRow resolves data.indexOfField[i] = data.outputRowMeta.indexOfValue(environmentSubstitute(meta.getFieldName()[i])) at the start of processing; any configured field name that is not present in the row coming from the previous step (or a typo / renamed field / wrong variable value after substitution) yields indexOfValue < 0 and triggers the throw.

Common situations: The upstream step was renamed or removed and its output field disappeared; the field name contains a Kettle variable whose value resolves differently at runtime (e.g. on a slave server); the user typed the field name manually instead of picking it from the dropdown; copying the transformation between environments where upstream metadata changed.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/setvaluefield/SetValueField.java:82

      meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
        metaStore );

      data.indexOfField = new int[meta.getFieldName().length];
      data.indexOfReplaceByValue = new int[meta.getFieldName().length];
      for ( int i = 0; i < meta.getFieldName().length; i++ ) {
        // Check if this field was specified only one time
        for ( int j = 0; j < meta.getFieldName().length; j++ ) {
          if ( meta.getFieldName()[j].equals( meta.getFieldName()[i] ) ) {
            if ( j != i ) {
              throw new KettleException( BaseMessages.getString(
                PKG, "SetValueField.Log.FieldSpecifiedMoreThatOne", meta.getFieldName()[i], "" + i, "" + j ) );
            }
          }
        }

        data.indexOfField[i] = data.outputRowMeta.indexOfValue( environmentSubstitute( meta.getFieldName()[i] ) );
        if ( data.indexOfField[i] < 0 ) {
          throw new KettleStepException( BaseMessages.getString(
            PKG, "SetValueField.Log.CouldNotFindFieldInRow", meta.getFieldName()[i] ) );
        }
        String sourceField = environmentSubstitute(
          meta.getReplaceByFieldValue() != null && meta.getReplaceByFieldValue().length > 0
            ? meta.getReplaceByFieldValue()[i] : null
        );
        if ( Utils.isEmpty( sourceField ) ) {
          throw new KettleStepException( BaseMessages.getString(
            PKG, "SetValueField.Log.ReplaceByValueFieldMissing", "" + i ) );
        }
        data.indexOfReplaceByValue[i] = data.outputRowMeta.indexOfValue( sourceField );
        if ( data.indexOfReplaceByValue[i] < 0 ) {
          throw new KettleStepException( BaseMessages.getString(
            PKG, "SetValueField.Log.CouldNotFindFieldInRow", sourceField ) );
        }
        // Compare fields type
        ValueMetaInterface SourceValue = getInputRowMeta().getValueMeta( data.indexOfField[i] );
        ValueMetaInterface ReplaceByValue = getInputRowMeta().getValueMeta( data.indexOfReplaceByValue[i] );

View on GitHub (pinned to f3058517a1)