pentaho/pentaho-kettle · error · KettleException

GPLoad.Exception.MatchColumnsNeeded

Error message

GPLoad.Exception.MatchColumnsNeeded

What it means

Thrown by GPLoad.getControlFileContents when the load action is MERGE or UPDATE but no match columns are configured. Merge/Update in gpload require the MATCH_COLUMNS list in the control file; the step validates matchColumn is non-null and that the metadata actually contains match columns (meta.hasMatchColumn()).

Solutions

  1. Open the GPLoad step and add match columns under the Match Columns tab (key fields for MERGE/UPDATE)
  2. Use Get Fields/lookup to map stream keys to table keys, then save
  3. Alternatively change the load action to INSERT or LOAD if matching is not intended
  4. Call meta.hasMatchColumn() in any programmatic use before generating the control file

Example fix

// before
meta.setLoadAction( GPLoadMeta.ACTION_MERGE );
// matchColumn never set -> KettleException MatchColumnsNeeded
// after
meta.setLoadAction( GPLoadMeta.ACTION_MERGE );
meta.setMatchColumn( new String[] { "id" } ); // key columns for MERGE
Defensive patterns

Strategy: validation

Validate before calling

if ( ( GPLoadMeta.ACTION_MERGE.equals( meta.getLoadAction() )
    || GPLoadMeta.ACTION_UPDATE.equals( meta.getLoadAction() ) )
    && !meta.hasMatchColumn() ) {
  throw new IllegalStateException( "MERGE/UPDATE require match columns" );
}

Type guard

boolean needsMatchCols = a -> GPLoadMeta.ACTION_MERGE.equals( a ) || GPLoadMeta.ACTION_UPDATE.equals( a );

Try / catch

try { gpload.getControlFileContents(); } catch ( KettleException e ) { if ( e.getMessage().contains( "MatchColumnsNeeded" ) ) { /* add match columns or change action */ } }

Prevention

When it happens

Trigger: Executing a GPLoad step whose loadAction is 'Merge' or 'Update' while the Match Columns table in the dialog is empty, or matchColumn metadata is null/stale.

Common situations: User switched load action from INSERT/LOAD to MERGE/UPDATE without adding match column mappings; transformation edited via metadata API leaving matchColumn null; mapping cleared after upstream field changes.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at plugins/gpload/core/src/main/java/org/pentaho/di/trans/steps/gpload/GPLoad.java:179

    if ( Utils.isEmpty( schemaName ) ) {
      schemaName = databaseMeta.getPreferredSchemaName();
    }
    if ( Utils.isEmpty( schemaName ) ) {
      schemaName = "";
    } else {
      schemaName = schemaName + ".";
    }
    targetTableName = schemaName + databaseMeta.quoteField( targetTableName );

    String loadAction = meta.getLoadAction();

    // match and update column verification
    if ( loadAction.equalsIgnoreCase( GPLoadMeta.ACTION_MERGE )
        || loadAction.equalsIgnoreCase( GPLoadMeta.ACTION_UPDATE ) ) {

      // throw an exception if we don't have match columns
      if ( matchColumn == null ) {
        throw new KettleException( BaseMessages.getString( PKG, "GPLoad.Exception.MatchColumnsNeeded" ) );
      }

      if ( !meta.hasMatchColumn() ) {
        throw new KettleException( BaseMessages.getString( PKG, "GPLoad.Exception.MatchColumnsNeeded" ) );
      }

      // throw an exception if we don't have any update columns
      if ( updateColumn == null ) {
        throw new KettleException( BaseMessages.getString( PKG, "GPLoad.Exception.UpdateColumnsNeeded" ) );
      }

      if ( !meta.hasUpdateColumn() ) {
        throw new KettleException( BaseMessages.getString( PKG, "GPLoad.Exception.UpdateColumnsNeeded" ) );
      }
    }

    // data file validation
    String dataFilename = meta.getDataFile();

View on GitHub (pinned to f3058517a1)