pentaho/pentaho-kettle · error · KettleStepException

ConcatFields.Error.TargetFieldNotFoundOutputStream

Error message

ConcatFields.Error.TargetFieldNotFoundOutputStream

What it means

ConcatFields concatenates several input fields into one target field. During processRow, after building the output row metadata, the step looks up the configured target field name in the output row metadata. If indexOfValue returns -1 (the target field is not present), it throws this KettleStepException.

Solutions

  1. Set a valid, non-empty Target field name in the Concat Fields step settings.
  2. Verify the target field name exactly matches (case-sensitive) what getFieldsModifyInput produces in the output stream.
  3. Re-open and re-save the transformation so the step metadata is refreshed.
  4. In test/code-driven usage, call meta.getFields(...) to inject the target field into outputRowMeta before processRow.

Example fix

// before
meta.setTargetFieldName( null );
// after
meta.setTargetFieldName( "concatenated" );
Defensive patterns

Strategy: validation

Validate before calling

if ( meta.getTargetFieldName() == null || outputRowMeta.indexOfValue( meta.getTargetFieldName() ) < 0 ) {
  throw new IllegalArgumentException( "Target field not in output stream: " + meta.getTargetFieldName() );
}

Try / catch

try {
  step.processRow();
} catch ( KettleStepException e ) {
  if ( e.getMessage().contains( "TargetFieldNotFoundOutputStream" ) ) {
    logError( "Check the Concat Fields target field name: " + e.getMessage() );
  }
}

Prevention

When it happens

Trigger: meta.getTargetFieldName() is not found in data.outputRowMeta after getFieldsModifyInput ran — typically because the target field name is misspelled, empty, or getFields() was never applied to add the target field.

Common situations: Users rename or delete the target field in the step dialog but stale transformations reference it; programmatic metadata construction (as in the unit tests) forgets to set targetFieldName before calling processRow.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at plugins/core/impl/src/main/java/org/pentaho/di/trans/steps/concatfields/ConcatFields.java:79

    if ( r != null && first ) {
      first = false;

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

      // the field precisions and lengths are altered! see TextFileOutputMeta.getFields().
      // otherwise trim(), padding etc. will not work
      data.inputRowMetaModified = getInputRowMeta().clone();
      meta
        .getFieldsModifyInput( getTransMeta().getBowl(), data.inputRowMetaModified, getStepname(), null, null,
           this, repository, metaStore );

      data.posTargetField = data.outputRowMeta.indexOfValue( meta.getTargetFieldName() );
      if ( data.posTargetField < 0 ) {
        throw new KettleStepException( BaseMessages.getString(
          PKG, "ConcatFields.Error.TargetFieldNotFoundOutputStream", "" + meta.getTargetFieldName() ) );
      }

      data.fieldnrs = new int[ meta.getOutputFields().length ];
      for ( int i = 0; i < meta.getOutputFields().length; i++ ) {
        data.fieldnrs[ i ] = data.inputRowMetaModified.indexOfValue( meta.getOutputFields()[ i ].getName() );
        if ( data.fieldnrs[ i ] < 0 ) {
          throw new KettleStepException( BaseMessages.getString(
            PKG, "ConcatFields.Error.FieldNotFoundInputStream", "" + meta.getOutputFields()[ i ].getName() ) );
        }
      }

      meta.calcMetaWithFieldOptions( data );

      // prepare for fast data dump (StringBuilder size)
      data.targetFieldLengthFastDataDump = meta.getTargetFieldLength();
      if ( data.targetFieldLengthFastDataDump <= 0 ) { // try it as a guess: 50 * size
        if ( meta.getOutputFields().length == 0 ) {

View on GitHub (pinned to f3058517a1)