{"record":{"id":"358a4d104bccb6c9","repo":"pentaho/pentaho-kettle","slug":"gpload-exception-matchcolumnsneeded","errorCode":null,"errorMessage":"GPLoad.Exception.MatchColumnsNeeded","messagePattern":"GPLoad\\.Exception\\.MatchColumnsNeeded","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/gpload/core/src/main/java/org/pentaho/di/trans/steps/gpload/GPLoad.java","lineNumber":179,"sourceCode":"    if ( Utils.isEmpty( schemaName ) ) {\n      schemaName = databaseMeta.getPreferredSchemaName();\n    }\n    if ( Utils.isEmpty( schemaName ) ) {\n      schemaName = \"\";\n    } else {\n      schemaName = schemaName + \".\";\n    }\n    targetTableName = schemaName + databaseMeta.quoteField( targetTableName );\n\n    String loadAction = meta.getLoadAction();\n\n    // match and update column verification\n    if ( loadAction.equalsIgnoreCase( GPLoadMeta.ACTION_MERGE )\n        || loadAction.equalsIgnoreCase( GPLoadMeta.ACTION_UPDATE ) ) {\n\n      // throw an exception if we don't have match columns\n      if ( matchColumn == null ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"GPLoad.Exception.MatchColumnsNeeded\" ) );\n      }\n\n      if ( !meta.hasMatchColumn() ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"GPLoad.Exception.MatchColumnsNeeded\" ) );\n      }\n\n      // throw an exception if we don't have any update columns\n      if ( updateColumn == null ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"GPLoad.Exception.UpdateColumnsNeeded\" ) );\n      }\n\n      if ( !meta.hasUpdateColumn() ) {\n        throw new KettleException( BaseMessages.getString( PKG, \"GPLoad.Exception.UpdateColumnsNeeded\" ) );\n      }\n    }\n\n    // data file validation\n    String dataFilename = meta.getDataFile();","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/gpload/core/src/main/java/org/pentaho/di/trans/steps/gpload/GPLoad.java#L161-L197","documentation":"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()).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Open the GPLoad step and add match columns under the Match Columns tab (key fields for MERGE/UPDATE)","Use Get Fields/lookup to map stream keys to table keys, then save","Alternatively change the load action to INSERT or LOAD if matching is not intended","Call meta.hasMatchColumn() in any programmatic use before generating the control file"],"exampleFix":"// before\nmeta.setLoadAction( GPLoadMeta.ACTION_MERGE );\n// matchColumn never set -> KettleException MatchColumnsNeeded\n// after\nmeta.setLoadAction( GPLoadMeta.ACTION_MERGE );\nmeta.setMatchColumn( new String[] { \"id\" } ); // key columns for MERGE","handlingStrategy":"validation","validationCode":"if ( ( GPLoadMeta.ACTION_MERGE.equals( meta.getLoadAction() )\n    || GPLoadMeta.ACTION_UPDATE.equals( meta.getLoadAction() ) )\n    && !meta.hasMatchColumn() ) {\n  throw new IllegalStateException( \"MERGE/UPDATE require match columns\" );\n}","typeGuard":"boolean needsMatchCols = a -> GPLoadMeta.ACTION_MERGE.equals( a ) || GPLoadMeta.ACTION_UPDATE.equals( a );","tryCatchPattern":"try { gpload.getControlFileContents(); } catch ( KettleException e ) { if ( e.getMessage().contains( \"MatchColumnsNeeded\" ) ) { /* add match columns or change action */ } }","preventionTips":["Whenever changing load action to MERGE/UPDATE, populate Match Columns immediately","Verify match column mappings still exist after upstream schema changes","Validate with testYAMLContents before scheduled runs"],"tags":["kettle","gpload","configuration","merge","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}