pentaho/pentaho-kettle · error · KettleException

CloneRow.Error.NrCloneInFieldMissing

Error message

CloneRow.Error.NrCloneInFieldMissing

What it means

First-row validation in CloneRow.processRow: the option to add a clone-number field is enabled, but the Clone number field name is empty (after environment substitution), so the step has nowhere to write the clone counter.

Solutions

  1. Enter the input field name that contains the clone count in the CloneRow dialog
  2. Turn off 'nr clones in field?' and instead use the fixed 'Nr of clones' value
  3. Verify the variable used resolves to a non-empty value at runtime
  4. Add a design-time check that the configured field exists in the incoming stream

Example fix

// before
cloneRowMeta.setNrCloneField( null );  // nrCloneInField=true
// after
cloneRowMeta.setNrCloneField( "clone_count" );
Defensive patterns

Strategy: validation

Validate before calling

if (meta.isNrCloneInField() && Utils.isEmpty(meta.getNrCloneField())) {
  throw new IllegalArgumentException("NrCloneField is required when nrCloneInField=true");
}

Try / catch

catch (KettleException e) { if (e.getMessage().contains("NrCloneInFieldMissing")) { fail fast with config guidance; } }

Prevention

When it happens

Trigger: processRow with meta.isNrCloneInField()==true and getNrCloneField() empty (field name never entered, or variable resolves to empty).

Common situations: Enabling 'clone count from field' and forgetting to name the field; variable-based field name not set in the environment; step copied from a template missing the value.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at plugins/core/impl/src/main/java/org/pentaho/di/trans/steps/clonerow/CloneRow.java:86

        String realflagfield = environmentSubstitute( meta.getCloneFlagField() );
        if ( Utils.isEmpty( realflagfield ) ) {
          logError( BaseMessages.getString( PKG, "CloneRow.Error.CloneFlagFieldMissing" ) );
          throw new KettleException( BaseMessages.getString( PKG, "CloneRow.Error.CloneFlagFieldMissing" ) );
        }
      }
      if ( meta.isAddCloneNum() ) {
        String realnumfield = environmentSubstitute( meta.getCloneNumField() );
        if ( Utils.isEmpty( realnumfield ) ) {
          logError( BaseMessages.getString( PKG, "CloneRow.Error.CloneNumFieldMissing" ) );
          throw new KettleException( BaseMessages.getString( PKG, "CloneRow.Error.CloneNumFieldMissing" ) );
        }
      }

      if ( meta.isNrCloneInField() ) {
        String cloneinfieldname = meta.getNrCloneField();
        if ( Utils.isEmpty( cloneinfieldname ) ) {
          logError( BaseMessages.getString( PKG, "CloneRow.Error.NrCloneInFieldMissing" ) );
          throw new KettleException( BaseMessages.getString( PKG, "CloneRow.Error.NrCloneInFieldMissing" ) );
        }
        // cache the position of the field
        if ( data.indexOfNrCloneField < 0 ) {
          data.indexOfNrCloneField = getInputRowMeta().indexOfValue( cloneinfieldname );
          if ( data.indexOfNrCloneField < 0 ) {
            // The field is unreachable !
            logError( BaseMessages.getString( PKG, "CloneRow.Log.ErrorFindingField" )
              + "[" + cloneinfieldname + "]" );
            throw new KettleException( BaseMessages.getString(
              PKG, "CloneRow.Exception.CouldnotFindField", cloneinfieldname ) );
          }
        }
      } else {
        String nrclonesString = environmentSubstitute( meta.getNrClones() );
        data.nrclones = Const.toInt( nrclonesString, 0 );
        if ( log.isDebug() ) {
          logDebug( BaseMessages.getString( PKG, "CloneRow.Log.NrClones", "" + data.nrclones ) );
        }

View on GitHub (pinned to f3058517a1)