pentaho/pentaho-kettle · error · KettleException

CloneRow.Error.CloneNumFieldMissing

Error message

CloneRow.Error.CloneNumFieldMissing

What it means

CloneRow step requires the 'clone number' output field name when 'add clone num' is enabled. processRow substitutes meta.getCloneNumField() and throws this KettleException (after logging) if it is empty or null.

Solutions

  1. Set a non-empty 'Nbr of clones fieldname' in the CloneRow dialog (e.g. 'CloneNum')
  2. Disable 'Add clone num?' if the column is not needed
  3. Make sure the variable in the field name is populated before the transformation runs
  4. Validate step settings at design time instead of failing at runtime

Example fix

// before
cloneRowMeta.setCloneNumField( "${UNSET_VAR}" );
// after
cloneRowMeta.setCloneNumField( "CloneNum" );
Defensive patterns

Strategy: validation

Validate before calling

if (meta.isAddCloneNum() && Utils.isEmpty(meta.getCloneNumField())) {
  throw new IllegalArgumentException("Clone num field is required when addCloneNum=true");
}

Try / catch

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

Prevention

When it happens

Trigger: processRow with meta.isAddCloneNum()==true and getCloneNumField() empty after environment substitution (field name blank in dialog or resolves to empty).

Common situations: Checking 'Add clone num?' but leaving 'Nbr of clones fieldname' empty; a runtime variable that expands to nothing; metadata copied from an old step.

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

Appendix: source

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

      first = false;
      data.outputRowMeta = getInputRowMeta().clone();
      data.NrPrevFields = getInputRowMeta().size();
      meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
        metaStore );
      data.addInfosToRow = ( meta.isAddCloneFlag() || meta.isAddCloneNum() );

      if ( meta.isAddCloneFlag() ) {
        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 ) );

View on GitHub (pinned to f3058517a1)