pentaho/pentaho-kettle · error · KettleException

ClosureGenerator.Exception.ParentFieldNotFound

Error message

ClosureGenerator.Exception.ParentFieldNotFound

What it means

ClosureGenerator.processRow looks up the configured parent-id field in the incoming row metadata via indexOfValue(meta.getParentIdFieldName()). If the field is absent from the input stream (index < 0), it throws a KettleException with this message. It means the Parent ID field configured on the step does not exist in the rows entering the step.

Solutions

  1. Open the Closure Generator dialog and verify the Parent ID field name matches the incoming stream exactly
  2. Use 'Get Fields' in the dialog to pick from actual upstream fields
  3. Check upstream steps for renames/deletions of the field
  4. Preview the input rows to confirm the field exists

Example fix

// before: dialog has parent_field
Parent ID field: parent_field
// after (stream field is parentId)
Parent ID field: parentId
Defensive patterns

Strategy: validation

Validate before calling

// In a prior step or dialog check:
if (inputRowMeta.indexOfValue(parentFieldName) < 0) {
  throw new IllegalArgumentException("Parent field " + parentFieldName + " missing from stream");
}

Type guard

boolean hasField(RowMetaInterface rowMeta, String name) {
  return name != null && rowMeta.indexOfValue(name) >= 0;
}

Try / catch

try {
  step.processRow();
} catch (KettleException e) {
  if (e.getMessage().contains("ParentFieldNotFound")) {
    // fix field mapping in dialog and restart transformation
  }
}

Prevention

When it happens

Trigger: Running the Closure Generator step when the field named in 'Parent ID field' is not present in the input row layout — renamed upstream field, wrong field name configured, or wrong hop ordering.

Common situations: Renaming or removing the parent field in an earlier step, misspelling the field name in the dialog, connecting a different stream than intended.

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

Appendix: source

Thrown at plugins/core/impl/src/main/java/org/pentaho/di/trans/steps/closure/ClosureGenerator.java:67

      Object[] rowData = getRow();

      if ( rowData == null ) {
        data.reading = false;
      } else {
        if ( first ) {
          first = false;

          // Create the output row metadata
          //
          data.outputRowMeta = getInputRowMeta().clone();
          meta.getFields( getTransMeta().getBowl(), data.outputRowMeta, getStepname(), null, null, this, repository,
            metaStore );

          // Get indexes of parent and child field
          //
          data.parentIndex = getInputRowMeta().indexOfValue( meta.getParentIdFieldName() );
          if ( data.parentIndex < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "ClosureGenerator.Exception.ParentFieldNotFound" ) );
          }
          data.childIndex = getInputRowMeta().indexOfValue( meta.getChildIdFieldName() );
          if ( data.childIndex < 0 ) {
            throw new KettleException( BaseMessages.getString(
              PKG, "ClosureGenerator.Exception.ChildFieldNotFound" ) );
          }

          data.parentValueMeta = getInputRowMeta().getValueMeta( data.parentIndex );
          data.childValueMeta = getInputRowMeta().getValueMeta( data.childIndex );
        }

        // add values to the buffer...
        //
        Object parentId = rowData[ data.parentIndex ];
        Object childId = rowData[ data.childIndex ];
        data.map.put( childId, parentId );
      }

View on GitHub (pinned to f3058517a1)