pentaho/pentaho-kettle · error · KettleStepException

ReplaceString.Exception.FieldTypeNotString

Error message

ReplaceString.Exception.FieldTypeNotString

What it means

ReplaceString only supports replacing within String fields. For each configured field it checks the incoming value metadata type; if the type is not ValueMetaInterface.TYPE_STRING it throws KettleStepException 'ReplaceString.Exception.FieldTypeNotString' with the field name.

Solutions

  1. Convert the field to String upstream (e.g. 'Value Mapper', 'Formula', or Select values 'Metadata' tab change type to String).
  2. Select a different, String-typed field in the step settings.
  3. Change upstream input parsing (e.g. Text file input format) so the column arrives as String.

Example fix

// before: numeric field passed straight to ReplaceString
// row: amount (Integer)
// after: convert upstream in Select values (Metadata tab)
// amount: Integer -> String
meta.setFieldInStream( new String[] { "amount_as_string" } );
Defensive patterns

Strategy: type-guard

When it happens

Trigger: The configured 'In stream field' resolves to a field whose type is Integer, Number, Date, Boolean, etc., rather than String.

Common situations: Hooking ReplaceString directly to a CSV column parsed as a number; a Calculator/Formula step produced a numeric field; forgetting a 'Field to string'/Text file output string conversion upstream.

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/31fcbec62d019478. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/replacestring/ReplaceString.java:181

      data.numFields = meta.getFieldInStream().length;
      data.inStreamNrs = new int[data.numFields];
      data.outStreamNrs = new String[data.numFields];
      data.patterns = new Pattern[data.numFields];
      data.replaceByString = new String[data.numFields];
      data.setEmptyString = new boolean[data.numFields];
      data.replaceFieldIndex = new int[data.numFields];

      for ( int i = 0; i < data.numFields; i++ ) {
        data.inStreamNrs[i] = getInputRowMeta().indexOfValue( meta.getFieldInStream()[i] );
        if ( data.inStreamNrs[i] < 0 ) {
          throw new KettleStepException( BaseMessages.getString(
            PKG, "ReplaceString.Exception.FieldRequired", meta.getFieldInStream()[i] ) );
        }

        // check field type
        if ( getInputRowMeta().getValueMeta( data.inStreamNrs[i] ).getType() != ValueMetaInterface.TYPE_STRING ) {
          throw new KettleStepException( BaseMessages.getString(
            PKG, "ReplaceString.Exception.FieldTypeNotString", meta.getFieldInStream()[i] ) );
        }

        data.outStreamNrs[i] = environmentSubstitute( meta.getFieldOutStream()[i] );
        data.patterns[ i ] = buildPattern( !meta.getUseRegEx()[ i ], meta.getCaseSensitive()[ i ],
          meta.getWholeWord()[ i ], environmentSubstitute( meta.getReplaceString()[ i ] ), meta.isUnicode()[ i ] );

        String field = meta.getFieldReplaceByString()[i];
        if ( !Utils.isEmpty( field ) ) {
          data.replaceFieldIndex[i] = getInputRowMeta().indexOfValue( field );
          if ( data.replaceFieldIndex[i] < 0 ) {
            throw new KettleStepException( BaseMessages.getString(
              PKG, "ReplaceString.Exception.FieldRequired", field ) );
          }
        } else {
          data.replaceFieldIndex[i] = -1;
          data.replaceByString[i] = environmentSubstitute( meta.getReplaceByString()[i] );
        }

View on GitHub (pinned to f3058517a1)