pentaho/pentaho-kettle · error · KettleStepException

StringOperations.Exception.FieldTypeNotString

Error message

StringOperations.Exception.FieldTypeNotString

What it means

StringOperations throws this KettleStepException in processRow() when a configured input field exists but is not a String (checked via getValueMeta(...).isString()). String Operations (trim, cut, lower/upper, masking, etc.) only support String fields.

Solutions

  1. Add a 'Select Values' step converting the field to String before String Operations
  2. Choose a field that is already a String in the step dialog
  3. Cast the column to text at the source (SQL CAST or Text File input format)
  4. Re-check the row layout with a preview after the fix

Example fix

// before
String Operations: trim on created_at (Date)
// after
Select Values: created_at -> String (yyyy-MM-dd), then String Operations: trim on created_at
Defensive patterns

Strategy: validation

Validate before calling

RowMetaInterface input = transMeta.getPrevStepFields(stepMeta);
for (String f : sopMeta.getFieldInStream()) {
  int idx = input.indexOfValue(f);
  if (idx >= 0 && !input.getValueMeta(idx).isString()) {
    throw new IllegalStateException("Field must be String: " + f);
  }
}

Try / catch

try {
  trans.execute(null);
  trans.waitUntilFinished();
} catch (KettleException e) {
  if (e.getMessage().contains("FieldTypeNotString")) {
    // add Select Values conversion to String upstream, then re-run
  }
}

Prevention

When it happens

Trigger: On the first processed row when !getInputRowMeta().getValueMeta(data.inStreamNrs[i]).isString() for one of the configured getFieldInStream() fields — e.g. a numeric or Date field was selected.

Common situations: Source column type changed (schema drift); forgetting a 'Select Values' type conversion to String before the step; connecting the step to a stream where the field arrives as Integer/Date.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/stringoperations/StringOperations.java:239

      first = false;

      // What's the format of the output row?
      data.outputRowMeta = getInputRowMeta().clone();
      data.inputFieldsNr = data.outputRowMeta.size();
      meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
        metaStore );
      data.nrFieldsInStream = meta.getFieldInStream().length;
      data.inStreamNrs = new int[data.nrFieldsInStream];
      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {
        data.inStreamNrs[i] = getInputRowMeta().indexOfValue( meta.getFieldInStream()[i] );
        if ( data.inStreamNrs[i] < 0 ) { // couldn't find field!

          throw new KettleStepException( BaseMessages.getString( PKG, "StringOperations.Exception.FieldRequired", meta
              .getFieldInStream()[i] ) );
        }
        // check field type
        if ( !getInputRowMeta().getValueMeta( data.inStreamNrs[i] ).isString() ) {
          throw new KettleStepException( BaseMessages.getString( PKG, "StringOperations.Exception.FieldTypeNotString",
              meta.getFieldInStream()[i] ) );
        }
      }

      data.outStreamNrs = new String[data.nrFieldsInStream];
      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {
        data.outStreamNrs[i] = meta.getFieldOutStream()[i];
      }

      // Keep track of the trim operators locally for a very small
      // optimization.
      data.trimOperators = new String[data.nrFieldsInStream];
      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {
        data.trimOperators[i] = meta.getTrimType()[i];
      }
      // lower Upper
      data.lowerUpperOperators = new String[data.nrFieldsInStream];
      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {

View on GitHub (pinned to f3058517a1)