{"record":{"id":"2d5a2c2fb857eed9","repo":"pentaho/pentaho-kettle","slug":"stringoperations-exception-fieldtypenotstring","errorCode":null,"errorMessage":"StringOperations.Exception.FieldTypeNotString","messagePattern":"StringOperations\\.Exception\\.FieldTypeNotString","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/stringoperations/StringOperations.java","lineNumber":239,"sourceCode":"      first = false;\n\n      // What's the format of the output row?\n      data.outputRowMeta = getInputRowMeta().clone();\n      data.inputFieldsNr = data.outputRowMeta.size();\n      meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,\n        metaStore );\n      data.nrFieldsInStream = meta.getFieldInStream().length;\n      data.inStreamNrs = new int[data.nrFieldsInStream];\n      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {\n        data.inStreamNrs[i] = getInputRowMeta().indexOfValue( meta.getFieldInStream()[i] );\n        if ( data.inStreamNrs[i] < 0 ) { // couldn't find field!\n\n          throw new KettleStepException( BaseMessages.getString( PKG, \"StringOperations.Exception.FieldRequired\", meta\n              .getFieldInStream()[i] ) );\n        }\n        // check field type\n        if ( !getInputRowMeta().getValueMeta( data.inStreamNrs[i] ).isString() ) {\n          throw new KettleStepException( BaseMessages.getString( PKG, \"StringOperations.Exception.FieldTypeNotString\",\n              meta.getFieldInStream()[i] ) );\n        }\n      }\n\n      data.outStreamNrs = new String[data.nrFieldsInStream];\n      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {\n        data.outStreamNrs[i] = meta.getFieldOutStream()[i];\n      }\n\n      // Keep track of the trim operators locally for a very small\n      // optimization.\n      data.trimOperators = new String[data.nrFieldsInStream];\n      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {\n        data.trimOperators[i] = meta.getTrimType()[i];\n      }\n      // lower Upper\n      data.lowerUpperOperators = new String[data.nrFieldsInStream];\n      for ( int i = 0; i < meta.getFieldInStream().length; i++ ) {","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/stringoperations/StringOperations.java#L221-L257","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a 'Select Values' step converting the field to String before String Operations","Choose a field that is already a String in the step dialog","Cast the column to text at the source (SQL CAST or Text File input format)","Re-check the row layout with a preview after the fix"],"exampleFix":"// before\nString Operations: trim on created_at (Date)\n// after\nSelect Values: created_at -> String (yyyy-MM-dd), then String Operations: trim on created_at","handlingStrategy":"validation","validationCode":"RowMetaInterface input = transMeta.getPrevStepFields(stepMeta);\nfor (String f : sopMeta.getFieldInStream()) {\n  int idx = input.indexOfValue(f);\n  if (idx >= 0 && !input.getValueMeta(idx).isString()) {\n    throw new IllegalStateException(\"Field must be String: \" + f);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  trans.execute(null);\n  trans.waitUntilFinished();\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"FieldTypeNotString\")) {\n    // add Select Values conversion to String upstream, then re-run\n  }\n}","preventionTips":["Convert non-String fields to String via Select Values before this step","Re-verify types after upstream source or query changes","Preview first rows to confirm runtime types","Keep a checklist of which steps require String inputs"],"tags":["row-stream","type-check","pdi","string"],"backgroundTag":"type-mismatch","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}