pentaho/pentaho-kettle · error · KettleException

ClosureGenerator.Exception.ChildFieldNotFound

Error message

ClosureGenerator.Exception.ChildFieldNotFound

What it means

ClosureGenerator.processRow looks up the configured child-id field in the input row metadata via indexOfValue(meta.getChildIdFieldName()). If absent (index < 0), it throws a KettleException with this message. Same root cause as the parent-field variant but for the Child ID field setting.

Solutions

  1. Verify the Child ID field name in the dialog against the actual input fields
  2. Use 'Get Fields' to select from the real stream
  3. Fix upstream steps that renamed or removed the child field
  4. Preview input rows to confirm field presence

Example fix

// before
Child ID field: child_id
// after (stream field is childId)
Child ID field: childId
Defensive patterns

Strategy: validation

Validate before calling

if (inputRowMeta.indexOfValue(childFieldName) < 0) {
  throw new IllegalArgumentException("Child field " + childFieldName + " 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("ChildFieldNotFound")) {
    // correct Child ID field in dialog
  }
}

Prevention

When it happens

Trigger: Running the Closure Generator step when the 'Child ID field' configured in the step metadata is not present in the incoming rows.

Common situations: Misspelled child field name, upstream field renamed/deleted, mixing up parent and child field entries in the dialog.

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

Appendix: source

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

        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 );
      }
    } else {
      // Writing the rows back...
      //
      for ( Object current : data.map.keySet() ) {
        data.parents = new HashMap<Object, Long>();

View on GitHub (pinned to f3058517a1)